# Valsight Documentation URL: https://docs.valsight.ai/ Description: Guides, references, and release notes for the Valsight platform, for humans and AI agents alike. Welcome to the Valsight documentation. Pick a section below to get started, or search from the bar above. This documentation is also served via MCP at `/mcp` (tools: `search_docs`, `get_doc`, `get_tree`, `list_templates`, `get_template`) and as plain markdown at `GET /api/doc/{slug}?audience=agent`. A full-text dump is available at `/llms-full.txt`. `/api/doc`, `/api/search`, and the `search_docs`/`get_doc` MCP tools accept an optional `version` (a public product id — unknown or unreleased ids are rejected with HTTP 400) to resolve docs for a specific release; omitted, they use the current default. `GET /api/versions` lists the valid ids. `/api/doc` responses carry `resolved_version`/`since`/`until`. --- # Release Notes 7.0.0 URL: https://docs.valsight.ai/7-0-0/ Description: This release introduces powerful new ways to work with Valsight, combining intelligent assistance, clearer scenario analysis, and a refined modelling experie… This release introduces powerful new ways to work with Valsight, combining intelligent assistance, clearer scenario analysis, and a refined modelling experience. Version 7.0.0 focuses on helping teams build, understand, and compare models more efficiently and with greater confidence. * **AI-powered guidance inside Valsight** * **A cleaner, more focused Model Editor** * **Flexible scenario comparisons in a single chart** ## AI-powered guidance inside Valsight The new [Valsight AI Assistant](https://docs.valsight.ai/ai-assistant/) helps you understand models, explore data, and navigate Valsight more effectively. By combining large language models with relevant Valsight context, the assistant can answer questions, explain concepts, and suggest next steps, while always respecting your permissions and requiring your explicit action. This makes it easier to onboard, document models, and gain clarity without leaving your workflow. ![Release 7-0\_Valsight AI Assistant.png](./images/6683492357.png) ## A cleaner, more focused Model Editor The [Model Editor](/model-editor-ui/) has been refined to reduce visual clutter and help you stay focused on the task at hand. Improvements to the **Function Editor**, [baseline handling](/working-with-different-model-baselines/), and overall layout create a cleaner, more structured editing environment that feels faster and more consistent. The updated design surfaces the right controls at the right time, making day-to-day modelling smoother and more intuitive. ![Model Editor.png](./images/6620446721.png)![Release 7-0\_Function Editor Redesign.png](./images/6620839937.png) ## Flexible scenario comparisons in a single chart ![Flexible scenario comparisons in a single chart.png](./images/6688014351.png) You can now [compare multiple scenarios in one chart](/configure-flexible-scenario-comparisons-in-a-single-chart/) while showing totals for some scenarios and detailed breakdowns for others. Individual level values can be hidden without removing them from the underlying configuration, making it easier to understand both overall differences and composition drivers in a single view. Hidden elements stay consistent across sessions, are excluded from legends, and are respected in chart exports. ## Other improvements * **Clickable Submodel Labels** Submodel labels displayed on nodes are now interactive. Double-clicking the label takes you directly to the corresponding submodel, making navigation across complex model structures faster and more intuitive, without changing existing node interaction behavior. For detailed information on these features and more, visit our documentation. Happy Simulating! --- # Release Notes 7.1.0 URL: https://docs.valsight.ai/7-1-0/ Description: This release brings greater consistency to multi-model projects with project-level baseline management, a cleaner and more reliable ROLLUP formula syntax, an… This release brings greater consistency to multi-model projects with project-level baseline management, a cleaner and more reliable ROLLUP formula syntax, and a set of usability improvements across the model editor. * **Manage baselines at the project level** * **Simplified and reliable ROLLUP syntax** ## Manage baselines at the project level Baselines are now defined once at the project level and are automatically available across all models in the project. A new "Baselines" section in Project Settings lets you create, color-code, rename, and safely delete baselines from a single location. Deleting a baseline that is still in use shows a full impact overview before any changes are made. [Learn more.](/baselines/) Video: [Project Settings\_baselines](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6889603074_Project-Settings_baselines.mov) ## Simplified and reliable ROLLUP syntax The ROLLUP function now only requires a level name, removing the dimension name argument that was previously accepted but silently ignored. This eliminates a long-standing source of incorrect results that produced no validation error. Existing models are migrated automatically to the new syntax; no manual changes needed. [Learn more](/rollup/). ## Other improvements * **Search for levels in the Function Editor** A search field is now available in the level picker popover, making it easy to find the right level by dimension or name without scrolling through long lists. * **Reposition dialogs freely while working** Dialogs across the model editor can be dragged and repositioned again, giving you the flexibility to move them out of the way when needed. For detailed information on these features and more, visit our documentation. Happy Simulating! --- # Release Notes 7.2.0 URL: https://docs.valsight.ai/7-2-0/ Description: 7.2 brings more precision to your planning models with dynamic project variables, chart axis breaks, bulk dimension-value deletion, and cross-submodel formula viewing. 7.2 brings more precision to your planning models. Define variables that calculate automatically, add visual breaks to charts with large value ranges, and navigate formulas across submodels with confidence. * **Dynamic project variables** * **Add breaks to chart axes** ## Dynamic project variables * Define variables that calculate automatically based on other variables: for example, set `$ForecastEnd` to always stay 12 months ahead of `$ForecastStart` * Write date formulas with autocomplete and syntax highlighting directly in the variable editor * All variables, fixed and dynamic, are available in node operations across your model * Fixed variables can still be overridden per scenario; dynamic variables always reflect their formula result ![Configure dynamic project variables in the variable editor](./images/configure-variables.png) [Learn more.](/project-variables/#dynamic-project-variables) ## Add breaks to chart axes * Add a visual break to the Y-axis on charts where values differ by large amounts, making all data points easier to read * Configure the break range and visual gap size directly in the chart's scale settings * Supported for line, bar, column, area, and bridge charts ![A Y-axis break on a chart with a large value range](./images/chart-axis-breaks.png) [Learn more.](/y-axis-breaks-in-charts/) ## Other improvements * **Delete dimension values in bulk** Upload dimension updates via Excel even when existing values are still in use. A warning callout identifies which rows are affected before you confirm the deletion. [Learn more.](/updating-level-values-via-data-source-upload/) * **View formulas across submodels** Open the Function Editor on any node and immediately see if it belongs to a different submodel: a lock icon and tooltip tell you where to go to edit it. The formula is visible but protected from accidental changes. For detailed information on these features and more, visit our documentation. Happy Simulating! --- # Release Notes 7.3.0 URL: https://docs.valsight.ai/7-3-0/ Description: 7.3 brings more direct control when building and presenting models, with in-place table-chart comparison editing, a smarter context-aware formula editor, and a redesigned Access Rights experience. 7.3 puts more direct control in your hands when building and presenting models. Edit table-chart comparisons in place, author formulas with a smarter, context-aware editor, and manage permissions through a redesigned Access Rights experience (now available as an opt-in beta). * **Edit comparisons in place** * **Redesigned Access Rights** Beta * **Smarter formula editor** ## Edit comparisons in place * Edit existing table-chart comparisons instead of deleting and rebuilding them from scratch * A new Edit Comparisons dialog lists all comparisons on the left with their full configuration on the right * Rename or reconfigure any comparison, pre-filled with its current settings * Edit several comparisons in a single session and apply everything with one Save (Cancel discards all changes) * Delete individual comparisons from the list; edited comparisons keep their position in the chart For more information, see [Delta Comparisons](/scenario-time-or-dimension-level-comparison-delta/). ## Redesigned Access Rights Beta This feature is available as a beta and must be opted in before it can be used. * A streamlined Access Rights matrix with a compact filter bar for projects, users and groups, and categories * Swap users/groups and objects between rows and columns with a single Pivot table button * Edit access directly from any matrix cell through a popover, with a plain-language "Why this access?" explanation * The per-holder editor groups permissions into collapsible per-project cards with sortable object lists * See each user's type at a glance with a colored badge in the matrix For more information, see [Managing Access Rights](/managing-access-rights/). ## Smarter formula editor * Autocomplete now suggests dimensions, levels, level values, data sources, and project variables — not just node arguments * Suggestions are context-aware and follow the dimension → level → level value hierarchy * Clear, human-readable messages when a formula has a problem: unknown functions (with "did you mean?" suggestions), unbalanced brackets, unclosed quotes, and missing separators * Inline signature help shows a function's parameters as you type * Fewer false errors on formulas that were valid all along For more information, see [Formula basics](/formula-basics/). ## Other Improvements * **Level search in the filter dialog** Type to filter levels in the chart editor's Filter dialog popover, matching dimension names first and then level names — no more scrolling through long lists. For more information, see [Chart Filter](/chart-filter/). * **Clearer model validation** Model validation now distinguishes blocking errors from non-blocking warnings, with per-severity counts in dialogs and node tooltips. Severity is readable at any zoom level — a red outline for errors and gold for warnings — and validation cascades correctly across sub-model boundaries. For more information, see [Model Validation](/model-validation/). *** For detailed information on these features and more, visit our documentation. Happy Simulating! --- # ABS URL: https://docs.valsight.ai/abs/ Description: Returns the absolute value for each value in the input node. Use this when you need to remove the sign from negative values. **Category:** [Math & numeric](/math-numeric/) ## Overview The **ABS** function **returns the absolute value** for each value in the input node. Use this function when you need to remove the sign from negative values. ## Syntax `ABS('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | ---------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | ## Examples ### Absolute value of positive, negative, and zero This example shows that negative values become positive, while positive values and zero remain unchanged. **Input node:** `'DecimalNode'` | Year | Value | | ---- | ----- | | 2025 | -24.5 | | 2026 | 95 | | 2027 | 0 | **Formula:** `ABS('DecimalNode')` | Year | ABS Result | | ---- | ---------- | | 2025 | 24.5 | | 2026 | 95 | | 2027 | 0 | --- # Abschreibungen URL: https://docs.valsight.ai/abschreibungen/ Description: Abschreibungen [Abschreibungen.pdf](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989924875_Abschreibungen.pdf) [Abschreibung Basisdaten.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989793821_Abschreibung-Basisdaten.xlsx) --- # Access Rights URL: https://docs.valsight.ai/access-rights/ Description: To activate changes made in the access management, users have to sign out and sign in again. Access rights define what each permission level can do per component: Projects, Models, Simulation Workspaces, Presentations, and Data Permission Classes. The tables below list the actions available at each level. *Important: To activate changes made in the access management, users have to sign out and sign in again.* ## Project | | Can use | Project admin | | -------------------------------------------------- | :----------------------------------: | :----------------------------------: | | See and enter Project | ✓ | ✓ | | Changing Project settings or Project access rights | ✗ | ✓ | | Access to Models and Workspaces within Project | ✗ | ✓ | ## Model Access to Project of Model is required | | Read-only | Can edit | | ----------------------------------------------- | :----------------------------------: | :----------------------------------: | | Open simulation Workspaces linked to Model | ✓ | ✓ | | Create new simulation Workspace linked to Model | ✗ | ✓ | | Open Model editor | ✗ | ✓ | | Change access rights to Model | ✗ | ✓ | ## Simulation workspace Access to Project of Model is required Limited/Full access also grants "Read-only" access to underlying Model | | Limited access | Full access | | ---------------------------------- | :----------------------------------: | :----------------------------------: | | Open and use Workspace | ✓ | ✓ | | Change Workspace filter | ✓ | ✓ | | Change access rights for Workspace | ✗ | ✓ | ## Presentation Presentations are not part of a Project. Any user with access rights to the presentation will be able to see and open it. | | Can access | | ------------------------------------ | :----------------------------------: | | See and open presentation | ✓ | | Change access rights to presentation | ✓ | | Delete presentation | ✓ | ## Data Permission Class Users with access can view or edit data associated with this data permission class in Workspaces or presentations. Users with access to the Model editor will be able to see all data while Modelling. | | Can view | Can edit | | ---------------------------------------------------------------------- | :----------------------------------: | :----------------------------------: | | View data in charts and tables in Workspaces or presentations | ✓ | ✓ | | Create and change assumptions containing data of data permission class | ✗ | ✓ | --- # Accessibility - WCAG Compliance URL: https://docs.valsight.ai/accessibility-wcag-compliance/ Description: Web accessibility is the inclusive practice of ensuring that people with disabilities can interact with websites. For our product development at Valsight this means we follow the WCAG 2.1 guidelines. Web accessibility is the inclusive practice of ensuring that people with disabilities can interact with websites. For our product development at Valsight this means we follow the [Web Content Accessibility Guidelines 2.1 (WCAG 2.1)](https://www.w3.org/TR/WCAG21/) and the [EN 301 549](https://www.barrierefreiheit-dienstekonsolidierung.bund.de/Webs/PB/DE/gesetze-und-richtlinien/en301549/en301549-node.html). Feel free to contact us in any accessibility-related question on the Valsight product or infrastructure, and particularly if you want to report a potential issue. Email: --- # Add a copyright or confidentiality notice URL: https://docs.valsight.ai/add-a-copyright-or-confidentiality-notice/ Description: On this page we will show you how to add and customize a copyright or confidentiality notice On this page we will show you how to add and customize a copyright or confidentiality notice ## Adding a copyright or confidentiality notice You may add a custom notice which will be visible on each slide in your presentations as well as in the print view. In addition to that, the notice will show inside simulation workspaces and when previewing data inside the model editor. ![2018-03-01 10-08-01.png](./images/5094190197.png) To do so, head to the project settings and edit the **featureFlags.workspaceSnapshotCopyrightNotice** field. ![2018-03-01 10-11-02.png](./images/5094190217.png) ![2018-03-01 10-10-35.png](./images/5094190302.png) ## Changing the color of the confidentiality notice Valsight also gives you the option to change the color of the confidentiality notice. To do so, head to the project settings and insert the **hex code** for the desired colour into **featureFlags.workspaceSnapshotCopyrightNoticeFontColor.** ![workspaceSnapshotCopyrightNotice.png](./images/5094190167.png) Your confidentiality notice will now be displayed in your desired colour. ![copyright-notice-colored-3.png](./images/5094190157.png)![copyright-notice-colored.png](./images/5094190162.png) > **Please keep in mind that confidentiality notices are adjusted on a per project basis.** --- # ADDEACH URL: https://docs.valsight.ai/addeach/ Description: The ADDEACH function adds a numeric value (or the values of another node) to each individual entry of a node before any aggregation is applied. **Category:** [Math & numeric](/math-numeric/) ## Overview The **ADDEACH** function **adds a numeric value** (or the values of another node) **to each individual entry of a node** before any aggregation is applied. Use this function when you need to apply an entry-by-entry adjustment to every value of a node while preserving the node’s dimensionality. ## Syntax `ADDEACH('Node', Amount)` `ADDEACH('Node', 'AmountNode')` **Example usage:** `ADDEACH('Growth Rate', 1)` ## Parameters | Parameter | Description | Type | Required | | ----------------------- | --------------------------------------------------------------------- | ------------------------ | -------- | | **Node** | The input node, referenced by name in single quotes (e.g. `'Profit'`) | Node reference | Yes | | **Amount / AmountNode** | A numeric value or another node to add to each entry | Number or node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | ----------------------------------------------------------- | | Dimensionality | Preserves the input shape | | Values | Each value of the node is increased by the specified amount | | Row count | Same number of rows as the input node | ## Watch out * ADDEACH performs entry-by-entry addition before rollups (automatic aggregation up hierarchies, e.g. months summing to quarters). * The `+` operator adds values **after** rolling them up to a common level. For example: * `'Node' + 5` first aggregates Node to a single total, then adds 5 once. * `ADDEACH('Node', 5)` adds 5 to every individual row before any aggregation. * When using another node as the Amount, the operation matches values across shared dimensions only. ## Examples ### Convert a percentage to a factor A growth rate of 5 % is stored as `0.05` in Valsight. To use it as a multiplication factor (`1.05`), add 1. **Formula:** `ADDEACH('Growth Rate', 1)` | Year | Growth Rate | ADDEACH Result | | ---- | ----------- | -------------- | | 2024 | 0.03 | 1.03 | | 2025 | 0.05 | 1.05 | | 2026 | 0.02 | 1.02 | ### Reverse a factor back to a percentage **Formula:** `ADDEACH('Factor', -1)` | Year | Factor | ADDEACH Result | | ---- | ------ | -------------- | | 2024 | 1.03 | 0.03 | | 2025 | 1.05 | 0.05 | ### Compute the complement (1 − x pattern) **Goal:** Compute 1 minus each value (e.g. if a share is 0.70, the complement is 0.30). **Why not** `1 - 'Split'`? In Valsight, that expression first rolls up 'Split' into a single total, then subtracts. **Solution:** Negate first with `'Split' * -1`, then add `1` to each entry. **Formula:** `ADDEACH('Split' * -1, 1)` | Product | VarCostSplit | ADDEACH Result | | ------- | ------------ | -------------- | | A | 0.70 | 0.30 | | B | 0.60 | 0.40 | Variable costs are 70 % / 60 % of total cost The formula therefore yields the fixed-cost share (30 % / 40 %). ### Flip 0/1 helper tables To invert a binary helper table (1 → 0, 0 → 1), apply the same pattern. **Formula:** `ADDEACH('Original Values' * -1, 1)` | Country | IS\_EMEA | ADDEACH Result | | ------- | -------- | -------------- | | DE | 1 | 0 | | US | 0 | 1 | Useful when you need the logical opposite of an existing flag, e.g. turning an IS\_EMEA flag into a NOT\_EMEA flag. ### Using a node as amount input Instead of a fixed number, you can pass a second node. ADDEACH then adds the values element-wise, matching on shared dimensions. Where the Amount node has no matching value, the original Node value is kept unchanged. Rows that exist only in the Amount node are not included in the result. **Node** | Year | Value | | ---- | ----- | | 2025 | 10 | | 2026 | 100 | | 2028 | 50 | **AmountNode** | Year | Value | | ---- | ----- | | 2024 | 100 | | 2025 | 150 | | 2026 | 200 | | 2027 | 250 | **Formula:** `ADDEACH('Node', 'AmountNode')` | Year | ADDEACH Result | | ---- | -------------- | | 2025 | 160 | | 2026 | 300 | | 2028 | 50 | Year 2024 and 2027 are absent because they only exist in AmountNode. Year 2028 has no match in AmountNode, so the original Node value (50) is preserved. The overlapping years are summed entry by entry: 10 + 150 = 160 100 + 200 = 300 ## Related | Function | When to use instead | | ---------------------------------------------------------------- | ---------------------------------------------------------------- | | [ADDITION (+)](/addition/) | When you want to add two nodes after rollup. | | [MULTIPLICATION (\*)](/multiplication/) / [MULTIPLY](/multiply/) | When you need element-wise multiplication instead of addition. | | [ROLLUP](/rollup/) | When you want to aggregate values after element-wise operations. | | [EXPAND](/expand/) | When you need to add dimensional detail before applying ADDEACH. | --- # ADDITION (+) URL: https://docs.valsight.ai/addition/ Description: The ADDITION operator adds two inputs after aligning them to their common dimensions. In other words, addition uses the intersection of the shared dimensions. **Category:** [Arithmetic operators](/arithmetic-operators/) ## Overview The **ADDITION** operator **adds two inputs** after aligning them to their **common dimensions**. In other words, addition uses the **intersection** of the shared dimensions. The result keeps the **coarser** level in each shared dimension. Dimensions that exist on only one side are aggregated away. Use this operator to combine values from two or more nodes. ## Syntax `'Node1' + 'Node2'` **Example usage:** `'Revenue BU1' + 'Revenue BU2'` ## Parameters | Parameter | Description | Type | Required | | --------- | ------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified in single quotes (e.g.`'Revenue BU1'`) | Node reference | Yes | | **Node2** | Second input node, specified in single quotes (e.g.`'Revenue BU2'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Dimensionality** | Both inputs are aggregated to their **common dimensions** (the **intersection** of the shared dimensions). Per shared dimension, the **coarser** level is used. Dimensions that exist on only one side are aggregated away. | | **Level values** | Non-matching level values are preserved in the result. | | **Row count** | Equal or reduced, depending on how much aggregation is required before adding. | ## Watch out * Addition uses the **common dimensions** (**intersection**), not the combined dimension set. This is different from multiplication and division. * When adding a constant such as `'Revenue' + 100`, the node is aggregated first and the constant is then added to the total. * To add a value to each entry before aggregation, use [ADDEACH](/addeach/) instead. * Both sides must have the same unit, unless one side is a scalar value. ## Examples ### Adding nodes with different dimensionality This example shows how addition aggregates `Node B` to the common dimensions before adding it to `Node A`. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 5 | | 2026 | 10 | **Input node:** `'B'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | A | 2 | | 2026 | A | 3 | | 2026 | B | 4 | **Formula:** `'A'+'B'` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 5+2 | 7 | | 2026 | 10+3+4 | 17 | ### Adding nodes with different level values When level values do not overlap, addition preserves both values in the result. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 5 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2026 | 10 | **Formula:** `'A' + 'B'` | Year | ADDITION Result | | ---- | --------------- | | 2025 | 5 | | 2026 | 10 | ### Adding a constant to a node When one operand is a constant, the node is aggregated first and the constant is then added to the total. **Input node:** `'Sales'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | A | 30 | | 2025 | B | 20 | **Formula:** `'Sales' + 100` | Year | Calculation | Result | | ---- | ------------- | ------ | | 2025 | 30 + 20 + 100 | 150 | ## Related | Function | When to use instead | | -------------------------------- | ------------------------------------------------------------------------------------------------------------ | | [UNION](/union/) | When both nodes have the same levels and you want to enforce that constraint (stricter version of ADDITION). | | [ADDEACH](/addeach/) | When you need to add a value to each individual entry before aggregation, rather than combining two nodes. | | [SUBTRACTION (-)](/subtraction/) | When you need tosubtract nodes instead of adding them. Uses the same roll-up logic. | --- # Additional Security Features URL: https://docs.valsight.ai/additional-security-features/ Description: - New users are redirected to change password on first login (admin can force that in the specified user's config page) Beyond authentication, Valsight offers password expiration rules, account and IP blocking after failed login attempts, and configurable HTTP security headers. ## Password rules & blocking * New users are redirected to change password on first login (admin can force that in the specified user's config page) * Passwords expire after <**N**> days, after which the users need to change their password * Can be changed by the passwordRules.passwordValidity flag in systems settings * Default value of <**N**> is 90 (days) Setting this value to 0 disables this functionality * Users get their account blocked for <**X**> minutes after <**Y**> wrong login attempts in the last <**Z**> hour * Configurable from flags in system settings (default values: <**X**> = 5, <**Y**> = 10, <**Z**> = 1) * FeatureFlags.blockMinutes = <**X**>, how many minutes the user will be unable to log in after he consecutively fails to login the specified amount of times. Setting this value to 0 will disable the blocking functionality * FeatureFlags.maxAttempts = <**Y**>, how many times the user must fail the login, before he gets blocked * FeatureFlags.saveAttemptsForNumberOfHours = <**Z**>, how long (hours) the user's failed login count is stored in the application. The failed count is reset after an successful login or when this amount of hours passes after the last unsuccessful login * IP blocking * Hard-coded to block IP upon 10 failed login attempts in 5 minutes * Admin can unblock users by: 1. Selecting them from users page & clicking on Unblock Selected Users 2. Uncheck "Blocked" box (displayed in the user page of blocked user) 3. (In the case of all accounts getting blocked, on-premise only) Specify user in config.yml (also used to enable user & change password): 1. password parameter optional, if none given, password will not be changed ``` unblock: username: foo password: bar ``` ## HTTP security headers HTTP Strict Transport Security Policy * Enabled from the application yml, informs the browser that app should be accessed over https --- # Admin Guide URL: https://docs.valsight.ai/admin-guide/ Description: What you will find in this section Instance-level administration in Valsight: managing users and groups, licenses and user types, security configuration, single sign-on, and the settings admins can customize. --- # Admin Password Reset URL: https://docs.valsight.ai/admin-password-reset/ Description: How to reset the admin user password directly in the application database of a Valsight On-Premise installation. You can reset the password of the "admin" user directly in the application database if it is no longer known. *Important: This article applies only to Valsight On-Premise. For Cloud installations, contact support.* Stop the Valsight instance before accessing the database. To reset the password of user "admin" back to "admin", run the following SQL command on the application's database. ```sql update app_user set local_password = '$2a$10$rTYJoj06.Fa16rLNDOkNouLvI2ovzjjyJ2EarynXsWyVF.HP0XQ7y' where username = 'admin'; ``` --- # Advanced Node Settings URL: https://docs.valsight.ai/advanced-node-settings/ Description: Advanced Node settings allow you to further fine-tune the behavior of a Node. You can hide technical Nodes by default or mark Nodes as base Assumptions. Advanced Node settings allow you to further fine-tune the behavior of a Node. You can hide technical Nodes by default or mark Nodes as base Assumptions. The **Advanced Settings** section of the Node Editor holds these controls, in this order: | Setting | What it does | | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | **Effect Description** | Free text shown as the node's effect description. | | **Default scale** | The scale a chart uses for this node when it has no scale of its own. | | **Default decimal places** | The number of decimals a chart uses for this node when it has none of its own. | | **Sort key** | Overrides where the node sorts, instead of by name. See [Sort Key Settings in Nodes](/sort-key-settings-in-nodes/). | | **Connector Color** | The color of the node's connectors, see below. | | **Hide outgoing connectors** / **Hide incoming connectors** | Hide connectors on one side, see below. | | **Hide in workspace** | Keep the node out of chart creation and tree charts, see below. | | **Include in export** | Include the node and its data in exports, see below. | | **Operation per baseline** | Lets the node carry a different formula per baseline. See [Working with different model baselines](/working-with-different-model-baselines/). | | **Show data effect in bridges** | Break this node's own contribution out in a bridge. See [Data Effects Display in Bridge](/data-effects-display-in-bridge/). | | **Group key** | Groups this node with others under one bar in a bridge's data effects. See [Data Effects Display in Bridge](/data-effects-display-in-bridge/). | The node's ID is shown at the bottom of the section. The sections below cover the settings that need more than a line. ## Hide in Workspace Nodes that are marked as "*hide in workspace"* will be hidden by default. This means that they will not be shown when creating new Charts or as part of Model Tree Charts. You can override this behavior per Workspace using the setting "Hide technical Nodes". ## Connector display and color You can hide outgoing and incoming Connectors or color them in a different color (see picture with Connectors in orange). Hidden Connectors will still be shown when the Node is selected (see picture with hidden Connectors for the top right two Nodes). This setting won't have any effect on the Tree Chart in the Workspace. ![image2020-9-7\_14-54-57.png](./images/5094213596.png) ## Including nodes in an export Via the node editor, nodes can be marked to be included in exports. When activating this function, the node and its data will automatically be included in the exports generated within this project. This is also helpful when creating templates, as there is an extra filter function for nodes marked for export. ![tempsnip1.png](./images/5094230916.png) --- # Aggregation Settings URL: https://docs.valsight.ai/aggregation-settings/ Description: 'Aggregation' is the process of reducing a data set's complexity by summarizing multiple values. 'Aggregation' is the process of reducing a data set's complexity by summarizing multiple values. This typically happens when viewing a data set with multiple dimensions in a chart that displays the data using only a subset of the available dimensions. In Valsight, you have the option to aggregate your data based on a number of options. The aggregation type of a node defines how the data is summarized and shown. The setting to define which aggregation type is applied can be found in the modeling section, in the Node Editor under **Aggregation Settings**. There are two aggregation setting types that influence the aggregation of your data ( *1.* [Display Aggregation Type](#display-aggregation-type)*, 2.* [Calculation Aggregation Type](#calculation-aggregation-type)). The effects of those two settings are visible when for example looking at the data in a tree view, as there the data is often shown on a per-year level. It also affects how the data is "Rolled up", if the [ROLLUP](/rollup/) or [DROPLEVEL](/droplevel/) function is used. ## Aggregation types Among the standard options you will find: | Aggregation Type | Description | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **SUM** (default) | Sum of all values. | | **AVG** | The average value. To calculate weighted averages, see below. | | **MIN / MAX** | The minimal/maximal value (on that specific aggregation level), e.g. can be a min-value per year & product | | **CLOSINGSUM** (Closing Date-Sum) | The sum of the values at the end of a period/dimension (e.g. sum of all Q4 revenue made from 2020-2022). | | **CLOSINGAVG** (Closing Date-Average) | The average value of all values at the end of a period/dimension (e.g. average of all Q4 revenue made from 2020-2022). | | **OPENINGSUM** (Opening Date-Sum) | The sum of the values at the beginning of a period/dimension (e.g. sum of all Q1 revenue made from 2020-2022). | | **OPENINGAVG** (Opening Date-Average) | The average value of all values at the beginning of a period/dimension (e.g. average of all Q1 revenue made from 2020-2022). | | **NONE** | The node will not be shown aggregated. | | **Weighted Average by** | You can specify a node that is used for weighting, e.g. use volume to weigh the price to get an average price of products sold. See details below. | | **LAST** | The last value from data will be shown, e.g. in a year dimension with data uploaded from 2024-01 till 2024-12, the LAST aggregation will take the value from 2024-12. If there is only data entered until 2024-05, then the LAST aggregation uses this data point. The value '0' counts as a data point. | | **FIRST** | The first existing value from data will be shown. The value '0' counts as a data point. | ## Examples To explain each aggregation type, imagine the following data set regarding R*evenue by country and year:* | Country | Year | Revenue | | ------- | ---- | ------- | | DE | 2023 | 100 | | US | 2023 | 200 | | DE | 2024 | 150 | | US | 2024 | 250 | ### SUM, AVERAGE, MIN, MAX Using these four different types, the aggregation results would look like this: | Year | SUM | AVG | MIN | MAX | | ---- | --- | --- | --- | --- | | 2023 | 300 | 150 | 100 | 200 | | 2024 | 400 | 200 | 150 | 250 | ### CLOSINGSUM, CLOSINGAVG, OPENINGSUM, OPENINGAVG, LAST and FIRST The aggregation functions *CLOSINGSUM* and *CLOSINGAVG* are like the traditional *SUM* and *AVG* with the exception of how the dimension is aggregated. To outline the mechanics, let's consider the example from above for 2023 with quarters. | Country | Quarter | Year | Revenue | | ------- | ------- | -------- | ------- | | DE | Q1 | 2023 | 15 | | DE | Q2 | 2023 | 15 | | DE | Q3 | 2023 | 20 | | **DE** | **Q4** | **2023** | **50** | | US | Q1 | 2023 | 30 | | US | Q2 | 2023 | 30 | | US | Q3 | 2023 | 40 | | **US** | **Q4** | **2023** | **100** | When aggregating the data on *year* using CLOSINGSUM or CLOSINGAVG, the aggregation will take the CLOSING value of the period (which is Q4) and calculate the SUM or AVG over all countries. | Year | CLOSINGSUM | CLOSINGAVG | | ---- | ---------- | ---------- | | 2023 | 150 | 75 | > When there is no closing value (e.g. the last month in a year) there will be no value for that period. When aggregating the data on *year* using OPENINGSUM or OPENINGAVG, the aggregation will take the opening value of the period (which is Q1) and calculate the SUM or AVG over all countries. | Year | OPENINGSUM | OPENINGAVG | | ---- | ---------- | ---------- | | 2023 | 45 | 22,5 | > When there is no opening value (e.g. the first month in a year) there will be no value for that period. When aggregating the data on *country* and *year* using the LAST aggregation, the data will show the last value of DE in 2023 and the last value of US in 2023. | Year | Country | LAST | | ---- | ------- | ---- | | 2023 | DE | 50 | | 2023 | US | 100 | When aggregating the data on *country* and *year* using the FIRST aggregation, the data will show the first value of DE in 2023 and the first value of US in 2023. | Year | Country | FIRST | | ---- | ------- | ----- | | 2023 | DE | 15 | | 2023 | US | 30 | ### Weighted average by The standard aggregation types only use the data of the node itself. However, typical drivers are cost ratios, prices, etc that must be weighted by a volume to make sense on an aggregated level. The weighted average aggregation setting allows you to define such a node. When using the weighted average, keep the following in mind: * The weighting node needs to have at least the levels of the node. * The weighted average is not supported for nodes using the RATIO function. * The average is calculated as 'Node' \* 'Weight' / 'Weight'. When using the node in a chart, the aggregation to the requested chart dimensionality happens individually for the numerator ( 'Node' \* 'Weight') and the denominator ('Weight') before the division and always using SUM as aggregation method (independent of the aggregation settings of 'Node' and 'Weight'). ![image-20230614-151551.png](./images/5159321671.png) ![image-20230614-151729.png](./images/5159321678.png) ## Two types of aggregation settings In the aggregation settings, users can choose between "Display Aggregation Type" and "Calculation Aggregation Type". ### Display aggregation type The display aggregation settings relate to the numbers **displayed in the simulation workspace** (e.g tree charts or tables). The setting helps to individually configure charts based on relevant numbers and dependent on the use case. **Example**: Company A is selling 3 sorts of apples and needs information about the average price of an apple over all sorts sold for the year 2020. Aggregating the data based on 'SUM' or 'AVERAGE' would not help company A as neither setting provides relevant or useful information for the request. Therefore, the 'Display Aggregation' - setting is used. Herewith, the company can display the needed information in the workspace (e.g. for a presentation) without directly changing the calculation of the model. ### Calculation aggregation type The calculation aggregation settings are purely used for the background **calculation of data in the model.** Changes can only be set when the display aggregation setting is set to 'None' or 'Weighted Average by'. The settings of this option are not shown in the **simulation workspace**. --- # Valsight AI URL: https://docs.valsight.ai/ai-assistant/ Description: The Valsight AI Assistant is a conversational interface that helps you understand, explore, and navigate your Valsight models using natural language. It prov… Valsight AI lets you understand, explore, and work with your Valsight models using natural language. There are **two ways** to use it, both built on the same model context — your model structure, formulas, metadata, and project configuration. ## The two ways to use Valsight AI * **In-app Assistant** — communicate with the AI **directly inside Valsight**. You chat with it in the app while you work, and it answers using the context of your models. It is **read-only** today; the ability to have it build and change models for you is coming in a future release. * **Valsight MCP integration** — connect your **own external AI client** (such as Claude) to Valsight through the MCP server. The client then explores and changes your models from outside the app, inside a session whose scope and permissions you control. This is a **premium feature, available from Valsight 7.3.0** and included at no additional cost through the end of 2026. ## Which one to choose * Use the **in-app Assistant** when you want help without leaving Valsight — quick questions, orientation, and explanations while you work. * Use the **Valsight MCP integration** when you want to drive Valsight from your own AI client or agent, or combine it with other tools. This is the more technical option and is aimed at technical users. ## The pages in this section * [Using the AI Assistant](/using-the-ai-assistant/): how to work with the in-app Assistant * [FAQ: AI Assistant](/frequently-asked-questions-valsight-ai-assistant/): questions about the in-app Assistant * [Valsight MCP integration](/valsight-mcp-server/): connect an external AI client via the MCP server * [FAQ: Valsight MCP integration](/frequently-asked-questions-valsight-mcp-integration/): connecting, security, and prerequisites --- # All functions (A-Z) URL: https://docs.valsight.ai/all-functions-a-z/ Description: This page is the complete alphabetical index of all functions available in node formulas. This page is the **complete alphabetical index of all functions available** in node formulas. Use it to find a function quickly and open the corresponding function page for syntax, parameters, and examples. ## How to use this page * Search the **Function** column (`Ctrl` / `Cmd` + `F`) to jump to a function name * Use **Category** to confirm you’re in the right function family ## A-Z index Function names link to the full function page. | Function | Category | Description | | ----------------------------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | [ABS](/abs/) | Math & numeric | Returns the absolute value of each value in the node. | | [ADDEACH](/addeach/) | Math & numeric | Adds the specified amount to each row in the node without aggregation. | | [ADDITION (+)](/addition/) | Arithmetic operators | Adds up nodes by rolling them up to the same set of levels (intersect). | | [AND (&&)](/and/) | Logical functions | Returns 1 (true) if both inputs are true; otherwise 0 (false). | | [API\_CALL](/api-call/) | Data access | Calls an external application with an HTTP POST request to a specified URL and returns the result to the model. | | [ARIMA](/arima/) | Rollforward & time series | Forecasts values using an autoregressive integrated moving average (ARIMA) model. | | [BASELINE](/baseline/) | Assumptions & result sets | Returns the value of a node with no assumptions applied on the node or anywhere upstream. | | [CAGR](/cagr/) | Compare periods | Calculates the compound annual growth rate over a specified number of periods. | | [DATA](/data/) | Data access | References a data table directly and returns its values. | | [DELTA\_ABS](/delta-abs/) | Compare periods | Calculates the absolute difference between consecutive values within the selected dimension. | | [DELTA\_REL](/delta-rel/) | Compare periods | Calculates the relative difference between consecutive values within the selected dimension. | | [DEPRECIATION](/depreciation/) | Finance functions | Calculates straight-line depreciation per period from initial value and depreciation time. | | [DISAGGREGATE](/disaggregate/) | Assumptions & result sets | Distributes values of one node onto a level based on another node’s value distribution (legacy; use DISTRIBUTE). | | [DISTRIBUTE](/distribute/) | Dimensionality & hierarchies | Distributes values of one node across levels based on another node’s value distribution. | | [DIVIDE](/divide/) | Math & numeric | Divides the first input by the second with optional validation that provides detailed errors on mismatches. | | [DIVISION (/)](/division/) | Arithmetic operators | Divides nodes by performing a join along the shared levels of the nodes (dimension union). | | [DROPLEVEL](/droplevel/) | Dimensionality & hierarchies | Removes one or more levels (and any finer levels in the same dimension) from the node. | | [ENUM](/enum/) | Filtering & data shaping | Numbers rows in ascending or descending order by value magnitude. | | [ENUM\_LEVEL](/enum-level/) | Filtering & data shaping | Numbers level values ascending or descending in the order defined in dimension management. | | [EQ (=)](/eq/) | Logical functions | Returns 1 (true) if matching row values across two nodes are equal; otherwise 0 (false). | | [EXP](/exp/) | Math & numeric | Calculates *e* (≈2.718) raised to the power of the input values. | | [EXPAND](/expand/) | Dimensionality & hierarchies | Expands a node or a specified value by adding the full cross product of the specified levels. | | [EXPANDSINGLE](/expandsingle/) | Dimensionality & hierarchies | Expands a node or a value to the specified level values. | | [FACT](/fact/) | Math & numeric | Returns the factorial of each input value. | | [FALSE](/false/) | Logical functions | Returns 0 (false) for every defined value in the node. | | [FILLMISSING](/fillmissing/) | Filtering & data shaping | Fills missing level values for a dimension into the node’s data. | | [FILLMISSING\_LAST](/fillmissing-last/) | Filtering & data shaping | Fills missing level values for a dimension with the last available value in the node. | | [FILL\_NA](/fill-na/) | Filtering & data shaping | Fills missing (NA) values for existing level combinations after pivoting a dimension into columns. | | [FILTER](/filter/) | Filtering & data shaping | Filters the node to rows where the specified level satisfies the filter operation. | | [FINDFIRST](/findfirst/) | Filtering & data shaping | Returns the first value per group defined by the specified level. | | [FINDMISSING](/findmissing/) | Filtering & data shaping | Marks missing level values between two nodes as 1 and existing ones as 0. | | [FV](/fv/) | Finance functions | Calculates the future value of a recurring annuity given interest rate, periods, and payments. | | [GT (>)](/gt/) | Logical functions | Returns 1 (true) where the first input is greater than the second. | | [GTE (>=)](/gte/) | Logical functions | Returns 1 (true) where the first input is greater than or equal to the second. | | [IF](/if/) | Logical functions | Returns value\_if\_true when a condition is true; otherwise returns value\_if\_false. | | [IRR](/irr/) | Finance functions | Calculates the internal rate of return. | | [IS\_NA](/is-na/) | Logical functions | Returns 1 (true) where values are undefined in the input node’s dimensionality; otherwise 0. | | [LEVELFILTER](/levelfilter/) | Filtering & data shaping | Filters the node to rows where a comparison between two level values meets a specified condition. | | [LN](/ln/) | Math & numeric | Returns the natural logarithm of the input. | | [LOG](/log/) | Math & numeric | Returns the logarithm of a value with respect to a specified base. | | [LOOKUP](/lookup/) | Filtering & data shaping | Looks up a value in an index table and returns the corresponding value from a return table using threshold (approximate) matching. | | [LT (<)](/lt/) | Logical functions | Returns 1 (true) where the first node’s values are less than the second. | | [LTE (<=)](/lte/) | Logical functions | Returns 1 (true) where the first node’s values are less than or equal to the second. | | [MAX](/max/) | Math & numeric | Returns the row-wise maximum of two nodes. | | [MIN](/min/) | Math & numeric | Returns the row-wise minimum of two nodes. | | [MOD](/mod/) | Math & numeric | Returns the remainder after dividing the first input by the second. | | **MODULO (%)** (see [MOD](/mod/)) | Arithmetic operators | Returns the remainder after dividing the first input by the second. Same result as MOD without validation. | | [MOM\_ABS](/mom-abs/) | Compare periods | Returns absolute month-over-month growth compared to the previous month. | | [MOM\_REL](/mom-rel/) | Compare periods | Returns relative month-over-month growth compared to the previous month. | | [MOVINGAVG](/movingavg/) | Rollforward & time series | Returns the moving average of the current value and preceding values, as defined by a time window. | | [MOVINGSUM](/movingsum/) | Rollforward & time series | Returns the moving sum of the current value and preceding values, as defined by a time window. | | **MTD** (see [YTD](/ytd/)) | Rollforward & time series | Returns month-to-date values as a running sum per month over the lowest time level. | | [MULTIPLY](/multiply/) | Math & numeric | Multiplies inputs with optional validation that provides detailed errors on mismatches. | | [MULTIPLICATION (\*)](/multiplication/) | Arithmetic operators | Multiplies nodes by performing a join along the shared levels of the nodes (dimension union). | | [NEQ (!=)](/neq/) | Logical functions | Returns 1 (true) where matching values of two nodes are not equal. | | [NONSIM](/nonsim/) | Assumptions & result sets | Returns a node’s value without assumptions on the node itself while applying assumptions upstream. | | [NOT](/not/) | Logical functions | Inverts logical values (non-zero becomes 0; zero becomes 1). | | [NPER](/nper/) | Finance functions | Calculates the number of periods for an investment given rate, payment, and present value. | | [NPV](/npv/) | Finance functions | Calculates net present value from a discount rate and a series of cash flows. | | [OR (\|\|)](/or/) | Logical functions | Returns 1 (true) if at least one of the two inputs is true; otherwise 0 (false). | | [PM](/pm/) | Compare periods | Returns the values for the previous month. | | [PMT](/pmt/) | Finance functions | Calculates the periodic payment for an investment given rate, periods, and present value. | | [POWER](/power/) | Math & numeric | Raises values from the first node to exponents from the second input. | | [PQ](/pq/) | Compare periods | Returns the values for the previous quarter. | | [PREVIOUS](/previous/) | Rollforward & time series | Returns the previous period’s value, except at a base period where it takes a specified base node value, enabling loop calculations. | | [PV](/pv/) | Finance functions | Calculates present value given rate, periods, payments, and future value/type. | | [PW](/pw/) | Compare periods | Returns the values for the previous week. | | [PY](/py/) | Compare periods | Returns the values for the previous year. | | [QOQ\_ABS](/qoq-abs/) | Compare periods | Returns absolute quarter-over-quarter growth compared to the previous quarter. | | [QOQ\_REL](/qoq-rel/) | Compare periods | Returns relative quarter-over-quarter growth compared to the previous quarter. | | **QTD** (see [YTD](/ytd/)) | Rollforward & time series | Returns quarter-to-date values as a running sum per quarter over the lowest time level. | | [RATE](/rate/) | Finance functions | Solves for the interest rate per period of an annuity given periods, payments, present value, and optional parameters. | | [RATIO](/ratio/) | Math & numeric | Divides the first node by the second while retaining only joint dimensions. Must be an end node; the result cannot be used in further calculations. | | [REBOOK](/rebook/) | Dimensionality & hierarchies | Rebooks numeric values from one level value to another within the same level. | | [REDISTRIBUTE](/redistribute/) | Dimensionality & hierarchies | Redistributes a value within specified clusters, weighted by a distribution measure. | | [ROLLFORWARD](/rollforward/) | Rollforward & time series | Projects a node into the future including the additive effects of defined driver nodes. | | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) | Rollforward & time series | Projects a node into the future including the effects of defined driver nodes and optional parameters (e.g., seasonal/average projection, aging logic). | | [ROLLFORWARD\_MUL](/rollforward-mul/) | Rollforward & time series | Projects a node into the future including the multiplicative effects of defined driver nodes. | | [ROLLUP](/rollup/) | Dimensionality & hierarchies | Aggregates a node to only the specified levels. | | [ROLLUP\_TO](/rollup-to/) | Dimensionality & hierarchies | Aggregates the first node to match the level dimensionality of the second node. | | [ROUND](/round/) | Math & numeric | Rounds each value to a specified number of decimal digits. | | [RUNNINGPROD](/runningprod/) | Rollforward & time series | Calculates the cumulative product along the time axis. | | [RUNNINGSUM](/runningsum/) | Rollforward & time series | Calculates the cumulative sum along the time axis. | | [SCHEDULEPROJECTS](/scheduleprojects/) | Rollforward & time series | Calculates a project KPI (e.g., revenue) over time given each project’s timing. | | [SHIFT](/shift/) | Compare periods | Shifts values along a specified level by a given offset (positive or negative). | | [SIGNUM](/signum/) | Math & numeric | Returns the sign of each number: 1 for positive, −1 for negative, 0 for zero. | | [SQRT](/sqrt/) | Math & numeric | Returns the square root of each value in the node. | | [STRETCH\_CURVE](/stretch-curve/) | Rollforward & time series | Stretches curves along the X-axis by a factor, starting at 0 by default or at an optional X position. | | [SUBTRACTION (-)](/subtraction/) | Arithmetic operators | Subtracts nodes by rolling them up to the same set of levels (intersect). | | [TIMELAG](/timelag/) | Rollforward & time series | Applies time-lagged effects at a given time granularity to model delays or growth curves. | | [TRUE](/true/) | Logical functions | Returns 1 (true) for every defined value in the node. | | [UNION](/union/) | Assumptions & result sets | Combines the result sets of two or more input nodes. | | [WOW\_ABS](/wow-abs/) | Compare periods | Returns absolute week-over-week growth compared to the previous week. | | [WOW\_REL](/wow-rel/) | Compare periods | Returns relative week-over-week growth compared to the previous week. | | **WTD** (see [YTD](/ytd/)) | Rollforward & time series | Returns week-to-date values as a running sum per week over the lowest time level. | | [XOR](/xor/) | Logical functions | Returns 1 (true) if exactly one of two inputs is true (exclusive OR). | | [YOY\_ABS](/yoy-abs/) | Compare periods | Returns absolute year-over-year growth compared to the previous year. | | [YOY\_REL](/yoy-rel/) | Compare periods | Returns relative year-over-year growth compared to the previous year. | | [YTD](/ytd/) | Rollforward & time series | Returns year-to-date values as a running sum per year over the lowest time level. | ## Project variable functions These functions work only in **dynamic project variables**, not in node formulas. See [Project variables](/project-variables/). | Function | Description | | ------------------------------- | ------------------------------------------------------------------------------------------ | | [DATE\_EXTRACT](/date-extract/) | Extracts the year, quarter, month, week, or day from a time level value. | | [DATE\_OFFSET](/date-offset/) | Offsets a time level value forward or backward by years, quarters, months, weeks, or days. | ## Related * [Browse by category](/browse-by-category/): find functions by modeling goal * [Operators](/operators/): arithmetic, comparisons, and boolean logic used inside formulas * [Formula basics](/formula-basics/): notation, references, constants, and evaluation fundamentals --- # Allow Simulation of Nodes URL: https://docs.valsight.ai/allow-simulation-of-nodes/ Description: This guide shows you how to mark nodes as simulatable so that their values can be changed in a simulation workspace. Mark nodes as simulatable so that their values can be changed in a simulation workspace. ## Prerequisites * You have an existing model with at least one node. * You have edit access to the model. ## Steps ### Open the model in the Model Editor ### Select the node you want to make simulatable Click the node on the canvas (for example, `Cost`). The Node Editor panel opens on the right. ### Enable the Allow Simulation toggle In the Node Editor, locate the **Allow Simulation** toggle and enable it. ![Allow simulation on node.png](./images/6895403016.png) ### Repeat for each simulatable node Work through the remaining nodes whose values should be editable in a simulation workspace. ## What you have done The selected nodes are now marked as simulatable. In a simulation workspace, users can override their values to explore different scenarios, while all other nodes remain read-only. ## Related * [Creating and Configuring Models](/creating-and-configuring-models/) * [Add Nodes to a Model](/creating-nodes/) * [Model Editor UI](/model-editor-ui/) --- # AND (&&) URL: https://docs.valsight.ai/and/ Description: Connects two inputs with the logical AND and returns true (1) if both values are true and false (0) otherwise. **Category:** [Logical functions](/logical-functions/) ## Overview The **AND** function **connects two inputs with the logical AND** and returns true (1) if both values are true and false (0) otherwise. Use this function when you need a 1/0 flag that becomes true only if both inputs are true at the same time. ## Syntax `AND('Node1', 'Node2')` `'Node1' && 'Node2'` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | | **Node2** | Second input node. | Node reference | Yes | ## Examples ### Typical use This example shows that `AND` returns 1 only when both inputs are true at the same time. If either input is 0, the result is 0. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 17 | | 2026 | 0 | | 2027 | 0 | | 2028 | 1 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 1 | | 2026 | 0 | | 2027 | 1500 | | 2028 | 12 | **Formula:** `AND('A', 'B')` | Year | AND Result | | ---- | ---------- | | 2025 | 1 | | 2026 | 0 | | 2027 | 0 | | 2028 | 1 | ## Related | Function | When to use instead | | ----------------- | ---------------------------------------------------------------------------------------------- | | [OR (\|\|)](/or/) | When at least one of the two inputs may be true instead of requiring both to be true. | | [XOR](/xor/) | When exactly one of the two inputs should be true instead of requiring both inputs to be true. | --- # Annotations URL: https://docs.valsight.ai/annotations/ Description: Annotations enable teams to add contextual information and visual structure directly to a model, making complex logic easier to understand and collaborate on… Annotations enable teams to add contextual information and visual structure directly to a model, making complex logic easier to understand and collaborate on without affecting calculations or results. ## When to use it * To explain model logic, assumptions, or decisions directly where they apply * To highlight related nodes or sections within large or complex models * To make models easier to review, hand over, or discuss with others * To visually separate different conceptual areas (e.g. inputs, calculations, KPIs) ## How it works Annotations are elements in the Model Editor that exist purely for documentation, orientation, and collaboration. They do not influence calculations or simulation results. **Three annotation types** are available: ### Frames Visually group related nodes using a labeled and color-coded container to indicate conceptual relationships. ![Frames\_Valsight.png](./images/6648397841.png) ### Sticky notes Free-form text elements placed anywhere in the model to add explanations, comments, or reminders. ![Sticky Notes\_Valsight.png](./images/6661373954.png) ### Dividers Vertical separators used to visually structure large models into clear sections. ![Dividers.png](./images/6648233986.png) Annotations can be shown or hidden globally via a toggle, allowing users to switch between a clean modeling view and a more documented view depending on their task. ## Using the feature * You can place annotations anywhere on the canvas to document or structure your model. * You can edit sticky note text directly by double-clicking it. * You can toggle annotation visibility to focus either on structure and documentation or on pure model logic. ## Limitations * Annotations are purely visual and informational; they never affect calculations or data. * Hidden annotations (including dividers) are not visible until re-enabled via the toggle. * Annotations do not enforce relationships: frames visually group nodes but do not create logical dependencies. ## FAQ **Can I reuse annotations in other models or projects?** Yes. Sticky notes and frames can be copied and pasted across models and projects. **What happens to dividers when annotations are hidden?** Dividers are hidden together with other annotation types. **Can annotations be attached to specific nodes?** Annotations can be positioned near nodes for context, but they are not technically bound to them. ## Related * [Model Editor UI](/model-editor-ui/) --- # API Access URL: https://docs.valsight.ai/api-access/ Description: Almost any part of the Valsight Application can be accessed via APIs. You can thereby freely integrate Valsight into your landscape, for example by regularly… **Almost any part of the Valsight Application can be accessed via APIs.** You can thereby freely integrate Valsight into your landscape, for example by regularly uploading data as data source, or as assumption. This section shows you the basics of how to interact with the system. If you need a custom integration, do not hesitate to contact your Valsight support team. --- # API_CALL URL: https://docs.valsight.ai/api-call/ Description: Enables Valsight to interact with external applications by making a POST call to a designated URL and returning the result to the Valsight model. **Category:** [Data access](/data-access/) > This function requires a separate subscription and is not available in all Valsight instances. ## Overview The **API\_CALL** function **sends node values to an external service** over an HTTP POST request and returns the service's response to the model as a node. Use this function when a calculation must run on an external system and the result should flow back into the model. If you are implementing the receiving service, see [Build a service for API\_CALL](/build-an-api-call-service/) for a worked example. ## Syntax `API_CALL(url, ['inputNodes'], ["resultLevels"] [, format, version, message, timeout])` **Example usage:** `API_CALL("https://example.com/sum", ['Node A', 'Node B'], ["Year", "Country"])` ## Parameters | Parameter | Description | Type | Required | Default | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | -------- | ------- | | **url** | The endpoint the POST request is sent to. Must match the allow-list configured by an administrator (see Availability & limits). | String | Yes | -- | | **inputNodes** | List of nodes, in square brackets, whose values are sent with the request. | List of node references | Yes | -- | | **resultLevels** | List of levels, in square brackets, that Valsight expects back from the service. These define the shape of the returned node. | List of level names | Yes | -- | | **format** | Data format of the response. Only `JSON` is supported. | String | No | `JSON` | | **version** | Version identifier sent with the request. Passed through untouched. | String | No | -- | | **message** | Free-text message sent with the request. Passed through untouched. | String | No | -- | | **timeout** | Time limit for the call, in seconds. If the service does not respond in time, the request is cancelled. | Number | No | `30` | The four optional arguments are **positional and nested**: to pass `timeout` you must also pass `format`, `version` and `message` before it. There is no way to skip an earlier one. ## Output shape | Aspect | Behavior | | -------------- | -------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Per dimension, the deepest level listed in `resultLevels`. Listing both `Year` and `Quarter` produces a node on `Quarter` alone. | | Values | Taken from the service's response, parsed from the Valsight Table JSON payload. | | Row count | Determined by the rows the service returns. | The response is validated against every level named in `resultLevels`, in the order written, even where the node itself ends up on fewer levels. ## Watch out * **The response must follow the Valsight Table JSON structure**, otherwise it cannot be converted into a node. See [Response format](#response-format). * **The HTTP status must be in the 200–299 range.** On anything else Valsight discards the body, so a message the service put in `error_message` never reaches the user. Report a business error as HTTP 200 with `response_status` set to `ERROR` instead. * **Input nodes are sent with full dimensionality.** A node dimensioned on `Month` alone arrives at the service carrying its `Year` and `Quarter` columns too. This is the only channel through which dimensionality is communicated, so a service should read the levels it needs by name and ignore the rest. * **Every value in `rowData` is a string**, numbers included. The service has to convert them. * Unknown keys in the response are ignored; only `response_status`, `error_message` and `output` are read. * If `response_status` is `ERROR`, Valsight surfaces the text in `error_message` and returns no data. * A node is recalculated on every user interaction. A service that takes seconds to answer makes the model feel unresponsive well before the `timeout` is reached. ## Availability & limits API\_CALL is off by default and is controlled by global feature flags that an administrator configures: * **`featureFlags.apiCall.allowedUrlsRegex`**: a Java regular expression of permitted URLs. Empty by default, which allows no URLs, so an administrator must set it before the function can be used. * **`featureFlags.apiCall.maxRowsToSend`**: maximum combined number of rows across all input nodes per request. Default `150000`. * **`featureFlags.apiCall.maxMbsToReturn`**: maximum response size read, in megabytes. Default `24`. ## Request format Valsight sends one POST request with `Content-Type: application/json` and this body: | Key | Value | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `inputs` | The input nodes, as an object keyed by each node's position in the formula, written as a string: `"0"`, `"1"`, and so on. Each value is a cube in Table JSON. | | `result_levels` | The level names from `resultLevels`. The encoding changed in 7.3, see the example below. | | `message` | The `message` argument, or `null` if it was omitted. | | `version` | The `version` argument, or `null` if it was omitted. | | `format` | Always `"JSON"`. | | `maximum_mbs_to_return` | The value of `featureFlags.apiCall.maxMbsToReturn`, as a string. | An example request body for `API_CALL("https://example.com/sum", ['Node A'], ["Year", "Country"], "JSON", "1", "a message")`: ``` { "inputs": { "0": { "version": "1", "columnMetadata": [ {"name": "Year", "columnType": "level", "levelId": 118}, {"name": "Country", "columnType": "level", "levelId": 101}, {"name": "measure", "columnType": "measure"} ], "tableMetadata": {"tableType": "FACT", "tableName": "Input 0"}, "rowData": [["2025", "DE", "100"], ["2026", "DE", "200"]] } }, "result_levels": ["Year", "Country"], "message": "a message", "version": "1", "format": "JSON", "maximum_mbs_to_return": "24" } ``` Because `message` and `version` are passed through untouched, they are a convenient way to switch behaviour in the service from the formula, without changing the interface. `result_levels` is a JSON array. Up to 7.2 it was a single string holding a rendered list, `"[Year, Country]"`, so a service written against an older Valsight that splits that string on commas has to be changed to read an array instead. This is a breaking change to the request body, made because a level name may itself contain a comma: `["Year", "Quarter, Q"]` used to arrive as `"[Year, Quarter, Q]"`, three comma-separated tokens for two levels. The array form is unambiguous. ## Response format Valsight validates a known set of keys in the response and ignores any others: * `response_status`: `SUCCESS` or `ERROR`. On `ERROR`, Valsight displays the message in `error_message`. The key may be omitted entirely; only an unrecognised value is an error. * `error_message`: the text shown to the user when `response_status` is `ERROR`. * `output`: the returned node, in the Valsight Table JSON structure. The `output` cube must carry exactly the levels named in `resultLevels`, plus a `measure` column. The most robust way to build its `columnMetadata` is to copy the entries from an input cube, because they carry the `levelId` values Valsight uses to map values back onto its dimensions. An example response: ``` { "format": "JSON", "version": "1", "function_name" : "simple_plus", "response_status": "SUCCESS", "error_message": "", "output" : { "version": "1", "columnMetadata": [ { "name": "Year", "columnType": "level", "levelId": 1 }, { "name": "measure", "columnType": "measure" } ], "rowData": [ ["2015","50"], ["2016","100"], ["2017","150"], ["2018","200"] ] } } ``` ## Errors Every message below is shown on the node, prefixed with `API_CALL -`. | Message | Cause | Fix | | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------- | | You have not entered a value for the URL. | The `url` argument is empty. | Enter an endpoint. | | No URLs are allowed. | `featureFlags.apiCall.allowedUrlsRegex` is empty, which is the default. | Ask an administrator to set the allow-list. | | The provided URL is not allowed. | The endpoint does not match the allow-list. | Correct the URL, or ask an administrator to widen the allow-list. | | The provided format is not supported. | The `format` argument is not `JSON`. | Use `JSON`, or omit the argument. | | The total number of rows in some of the input nodes is higher than the maximum. | The input nodes together exceed `maxRowsToSend`. | Reduce the input, or ask an administrator to raise the limit. | | The size of the content returned exceeds the maximum allowed limit. | The response is larger than `maxMbsToReturn`. | Return less data, or ask an administrator to raise the limit. | | The external server did not respond in the given time frame. | The service did not answer within `timeout` seconds. | Make the service faster, or raise `timeout`. | | The POST request to the external server failed. | The service answered with a status outside 200–299. | Check the service logs for the failing request. | | The external server failed to do the calculation. | The service returned `response_status` `ERROR`. | Read the service's own `error_message`, quoted in the notice. | | The external server returned an unknown response status. | `response_status` is present but is neither `SUCCESS` nor `ERROR`. | Return one of the two values, or omit the key. | | Unable to convert the output received from external server into a valid cube. | `output` is not valid Table JSON, or its levels do not match `resultLevels`. | Compare the cube against [Response format](#response-format). | ## Examples ### Sending two nodes to a service that adds them This example sends two nodes to a service that adds them and returns the sum per Year and Country. **Input node:** `'A'` | Year | Country | Revenue | | ---- | ------- | ------- | | 2025 | DE | 100 | | 2026 | DE | 200 | | 2027 | DE | 300 | | 2028 | DE | 400 | | 2029 | DE | 500 | **Input node:** `'B'` | Year | Country | Revenue | | ---- | ------- | ------- | | 2025 | DE | 350 | | 2026 | DE | 400 | | 2027 | DE | 450 | | 2028 | DE | 500 | | 2029 | DE | 550 | **Formula:** `API_CALL("https://externalServer.com/sumTwoNodes", ['Node A', 'Node B'], ["Year", "Country"])` Valsight sends nodes A and B as `inputs` `"0"` and `"1"`, and requests the levels Year and Country back. When the service responds successfully, the result is: | Year | Country | Calculation | Result | | ---- | ------- | ----------- | ------ | | 2025 | DE | 100 + 350 | 450 | | 2026 | DE | 200 + 400 | 600 | | 2027 | DE | 300 + 450 | 750 | | 2028 | DE | 400 + 500 | 900 | | 2029 | DE | 500 + 550 | 1050 | ### Switching behaviour from the formula This example uses `message` to pick a mode in the service without changing the interface. **Formula:** `API_CALL("https://externalServer.com/optimize", ['Volume'], ["Country"], "JSON", "1", "integer")` The service receives `"message": "integer"` and can branch on it, for instance to run an integer rather than a continuous optimisation. Passing `message` requires passing `format` and `version` first, because the optional arguments are positional. ## Related | Function | When to use instead | | -------------- | -------------------------------------------------------------------------------------------------------------------- | | [DATA](/data/) | When the external data is already uploaded as a data table, reference it directly instead of calling a live service. | --- # API keys login URL: https://docs.valsight.ai/api-keys-login/ Description: To configure the Valsight application to use the API keys login method, edit conf/config.yml and restart the server after making changes. To configure the Valsight application to use the API keys login method, edit *conf/config.yml* and restart the server after making changes. This login method is not a SSO method, but an alternative to standard username/password login. It is possible to login with API keys, even if the form login was disabled. API keys are stored as a hash in the database. | Configuration key (apiKeyAuth →) | Description | Example value | Default value | | -------------------------------- | ------------------------------------------------------------- | ------------- | ------------- | | `enabled` | Whether the API keys authentication method is allowed or not. | `true` | `false` | ## How to generate and remove API keys ![The user profile page with the Generate API Key and Delete all API keys buttons](./images/5094190317.png) ### Option 1: from your user profile Available since 4.7.0. #### To generate an API key 1. Navigate to **your profile via the navigation bar** 2. Click on the button 'Generate API Key' 3. The generated key is shown The leading and trailing are **not** part of the key. This is the **only time and place where you can see the generated key**. If you leave or reload the page with the displayed key, you will not be able to view it in the application again. #### How to remove an API key 1. Navigate to your profile via the navigation bar 2. Click on the button 'Delete all API keys' 3. All the API keys for your user are removed It is not possible to remove only one specific key for a user. ### Option 2: from the Valsight settings #### To generate an API key 1. In the **Valsight settings** navigate to the user profile 2. Click on the button 'Generate API key' 3. The generated key appears at the top The leading and trailing are **not** part of the key. This is the **only time and place where you can see the generated key**. If you leave or reload the page with the displayed key, you will not be able to view it in the application again. #### How to remove an API key 1. In the Valsight settings navigate to the user profile 2. Click on the button 'Delete all API keys' 3. All the API keys for that user are removed It is not possible to remove only one specific key for a user. *Important: Users can only access data via an API key if they have permission rights for the project, model or workspace.* ## How to log in with API keys 1. Make sure this login method is turned on in the config.yml 2. Use a valid API key 3. Create a form POST request to the endpoint '/v1/apiKey'. The form contains 2 parameter, 'username' and 'api\_key'. 4. If the combination username/key was valid the application will recognize the user from it and log him in. The response contains a cookie 'JSESSIONID' that the user can use to authenticate for subsequent requests. The cookie is present in the HTTP header 'Set-Cookie' in the response. You can see if the user logged in via API key or form in the 'Security audit log'. The login successful entry will have 'API key login' attached to it, if the user logged in via an API key. ## Logging For logging purposes, add the following package in the log level view of the Configuration UI: * Logger: com.valsight.authentication.apikey.ApiKeyAuthenticationProvider * Level: DEBUG --- # Applying Filters URL: https://docs.valsight.ai/applying-filters/ Description: The standard mode when it comes to applying filters in Valsight offers a quick and easy way to customize filter settings. It follows three basic rules: Filters can be applied in two modes: Standard Mode for bulk selection with automatic child checking, and Tree-Select Mode for precise what-you-see-is-what-you-get filtering. > **A filter must keep at least one value selected.** Leaving a level with nothing ticked is not a way to filter everything out: the dialog reports ‘All objects set as filters must have values selected.’ and **Save** stays disabled until you tick something. The ‘Deselect all’ icon below therefore leaves the dialog in a state you cannot save. ## Standard Mode The standard mode when it comes to applying filters in Valsight offers a quick and easy way to customize filter settings. It follows three basic rules: 1. “ALL” literally means ALL 1. When you use the “ALL” checkbox, all available checkboxes are checked, even though they might not be visible (e.g. after entering a search input) 2. When a parents' checkbox is checked, **all of its children** (and their children) will be checked as well, even though some might not be visible (e.g. after entering a search input) 3. A checked checkbox is not displayed until all children (and children’s children) are checked as well **The advantage** of this mode is an easily accessible bulk selection of items with direct visual confirmation. ![Standard Filter.gif](./images/5244158002.gif) ## Tree-Select Mode By using the ‘Alt’-button ('Options' for Mac) within the filter management, you enter the tree-select mode. This mode enables you to follow a fast ‘what-you-see-is-what-you-get’ approach to customize your filters. It follows four basic rules: 1. “ALL” means all displayed checkboxes 1. When you enter a search input and out of a total of 300 items, only 20 are displayed, clicking “ALL” will only select the 20 displayed items 2. Tree-selection 1. When a parent's checkbox is checked, **only the displayed** children (and children's children) will be checked as well (used in cases where search inputs are applied). That is contrary to the standard mode as there all children will be checked. 3. Parent checkboxes might also be checked even though not all children (or children's children) are checked (some children might not be displayed due to a search input) **The advantage** of this mode is a faster visual confirmation of a successful filter selection and the assurance that after a search input, only the visible checkboxes will be checked, although a certain parent might feature other children not matching the search input. ![Tree selec Filter.gif](./images/5244158008.gif) ### Icons The filter management offers the following icons: | Icon | Function | | :---------------------------------------------: | ----------------------------------------- | | ![Count icon](./images/5244158014.png) | Counts all lowest levels selected. | | ![Select-all icon](./images/select-all.svg) | Selects all checkboxes. | | ![Deselect-all icon](./images/deselect-all.svg) | Deselects all checkboxes. | | ![Expand-all icon](./images/expand-all.svg) | Expands all items to its lowest level. | | ![Collapse-all icon](./images/collapse-all.svg) | Collapses all items to the highest level. | | Usage | | -------------------------------------- | | Line-item creation and reconfiguration | | Workspace filter | | Worksheet filter | | Perspective Selector | | Template manager | | Chart editing | | Scenario export | --- # Arbeitsbereiche URL: https://docs.valsight.ai/arbeitsbereiche/ Description: Diese Seite bietet Tutorials und Anleitungen rund um das Thema Simulation. Diese Seite bietet Tutorials und Anleitungen rund um das Thema Simulation. ## Intro: Management Meetings erleichtern Video: [Intro: Management Meetings erleichtern](https://youtu.be/hHZpWNVelHE) In diesem Video zeige ich dir, wie du Valsight nutzen kannst, um Live-Management-Meetings effizienter und datenbasierter zu gestalten. Du lernst, wie du Dashboards für einen fiktiven Automobilhersteller nutzt, Szenarien simulierst und visualisierst, sowie wie Treiberbaummodelle Diskussionen unterstützen. ## Arbeitsbereich erstellen Video: [Arbeitsbereich erstellen](https://www.youtube.com/watch?v=wsog-2rtn3k) In diesem Video zeige ich dir, wie du einen neuen Arbeitsbereich in Valsight erstellst. Du lernst, einen Namen zu vergeben, das Modell und Szenario auszuwählen, die als Datenbasis für Simulationen dienen. Außerdem erfährst du, wie du den Arbeitsbereich anpasst und Diagramme, Bilder oder Texte hinzufügst, um deine Analysen zu visualisieren. [Mehr Details](/creating-a-workspace/) ## Szenario Manager Video: [Szenario Manager](https://www.youtube.com/watch?v=wdCXB5kSJic) In diesem Video zeige ich dir, wie du den Szenario Manager in Valsight verwendest, um Annahmen und Maßnahmen zu definieren und in Szenarien zu aktivieren. Du lernst, Annahmen zu erstellen, Line Items hinzuzufügen und Szenarien zu duplizieren. Außerdem wird erklärt, wie du Annahmen und Szenarien vergleichst und deren Auswirkungen analysierst. [Mehr Details](/scenario-manager/) ## Tabelle pivotieren Video: [Years in Columns](https://youtu.be/33zKjK9FQJc) In diesem Video erfährst du, wie du eine Line-Item-Tabelle pivotierst, um die Level eines Line-Items umzustellen und die Zeilen und Spalten nach deinen Präferenzen zu ordnen. Du lernst, zwischen Änderungs- und Ergebnisansicht zu wechseln, Dimensionen zu pivotieren, Filter zu setzen und diese Einstellungen nachhaltig zu speichern. > Das Video nennt die Funktion noch **Years in Columns**. In der Oberfläche heißt die Schaltfläche heute **Pivotieren**, ihr Tooltip **Tabelle pivotieren**. [Mehr Details](/creating-a-line-item/) ## Szenario-Brücke Video: [Szenariobrücke](https://youtu.be/Gih1f2vbHS0) In diesem Video lernst du, wie du in Valsight eine **Szenario-Brücke** und eine **Brücke zwischen Perioden (YoY)** erstellst, um die Effekte von Annahmen zwischen Szenarien oder über Jahre hinweg zu visualisieren. Es wird erklärt, wie du die Brücken erstellst, Szenarien vergleichst und die Analyse durch Anpassungen der Annahmen und Line Items verfeinerst. [Mehr Details](/bridges/) ## Schieberegler Video: [Schieberegler](https://www.youtube.com/watch?v=UPEk1TStjlM) In diesem Video lernst du, wie du mit Schiebereglern in Valsight Annahmen und Maßnahmen flexibel simulieren kannst. Du erfährst, wie Schieberegler für Live-Diskussionen genutzt werden, z. B. zur Simulation von Inflationseffekten. Zudem wird gezeigt, wie du Schieberegler anlegst, Einstellungen wie Mindest- und Höchstwerte anpasst und Simulationen visuell auswertest. [Mehr Details](/sliders-in-the-scenario-manager/) ## Filtermöglichkeiten im Arbeitsbereich Video: [Filtermöglichkeiten im Arbeitsbereich](https://youtu.be/fapzLHMP67A) In diesem Video lernst du, wie du in Valsight verschiedene Filteroptionen im Arbeitsbereich nutzt. Du erfährst, wie Diagrammfilter, Arbeitsblatt-Filter und Arbeitsbereich-Filter gesetzt werden, um die Daten auf spezifische Dimensionen, wie z.B. Regionen oder Produkttypen, zu begrenzen und somit Analysen effizienter zu gestalten. [Mehr Details](/filters-in-valsight/) --- # ARIMA URL: https://docs.valsight.ai/arima/ Description: Forecasting function based on the autoregressive integrated moving average (ARIMA) model. Use when you want to forecast a time series from historical patterns without defining explicit driver nodes. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **ARIMA** function is a **forecasting function based on the autoregressive integrated moving average (ARIMA) model**. [Learn more](https://towardsdatascience.com/time-series-forecasting-arima-models-7f221e9eee06). Use this function when you want to forecast a time series from historical patterns without defining explicit driver nodes. ## Syntax `ARIMA('Node', p, d, q, P, D, Q, m)` ## Parameters | Parameter | Description | Type | Required | | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Node that contains the base data for the forecast. It must contain at least one time level. Predictions are based on the time values in the node and extend to the end of the horizon period. | Node reference | Yes | | **p** | The order (number of time lags) of the autoregressive model. | Number | Yes | | **d** | The degree of differencing. | Number | Yes | | **q** | The order of the moving-average model. | Number | Yes | | **P** | Autoregressive term for the seasonal part. | Number | Yes | | **D** | Differencing term for the seasonal part. | Number | Yes | | **Q** | Moving average term for the seasonal part. | Number | Yes | | **m** | The number of periods in each season. | Number | Yes | ## Watch out * If the input data has a missing value in the time dimension, the calculation fails. A time value is considered missing if the data has actual value(s) before and after the missing value. For example, `[2019, 2021]` has missing value `2020`, but `[2020, 2021]` or `[2019, 2020]` have no missing values. ## Examples ### Monthly forecast from historical data This example shows monthly historical passenger data used as the basis for an `ARIMA` forecast. The result keeps the historical observations and extends the series with forecasted periods to the end of the horizon. **Input node:** `'Passenger historic'` Data set: [Passenger historic.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5094194005_Passenger-historic.xlsx) Data horizon: 2000 - 2011 | Year | Month | Value | | ---- | ------- | ----- | | 2000 | 2000-01 | 112 | | ... | ... | ... | | 2011 | 2011-12 | 432 | **Formula:** `ARIMA('Passenger historic', 1, 1, 1, 1, 0, 1, 12)` ARIMA horizon: 2000 - 2020 | Year | Month | ARIMA Result | | ---- | ------- | ------------ | | 2000 | 2000-01 | 112 | | ... | ... | ... | | 2011 | 2011-12 | 432 | | 2012 | 2012-01 | 450 | | ... | ... | ... | | 2020 | 2020-12 | 861 | The rows through 2011 repeat the historical input values unchanged; the rows from 2012 onward are the new forecasted periods. **Chart:** ![Line chart showing ARIMA-forecasted passenger numbers continuing the historical trend from 2000 to 2020](./images/5094231152.png) ## Related | Function | When to use instead | | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) | When you want to project values with explicit driver nodes instead of forecasting from historical patterns alone. | | [MOVINGAVG](/movingavg/) | When you want to smooth historical values over a rolling window instead of creating a forecast. | --- # Arithmetic operators URL: https://docs.valsight.ai/arithmetic-operators/ Description: Arithmetic operators combine numeric values in formulas. Use them for simple calculations, KPI logic, and combining driver nodes. Arithmetic operators **combine numeric values** in formulas. Use them for simple calculations, KPI logic, and combining driver nodes. When inputs have different dimensionality, arithmetic can also change the output shape. ## Start here if you want to: * Perform a calculation such as `'Revenue' + 'Other income'` * Combine driver nodes with `+`, `-`, `*`, `/`, or `%` * Understand how output shape changes when inputs have different dimensionality ## Not here if you want to: * Compare values or build a condition → see [Comparisons & boolean operators](/comparisons-boolean-operators/) * Use validated functions with stricter mismatch handling → see [RATIO](/ratio/), [MULTIPLY](/multiply/), [DIVIDE](/divide/), or [UNION](/union/) in the [function catalog](/function-catalog/) ## Mental model Arithmetic operators work row-wise on matching intersections of level values. When inputs do not have the same dimensionality, the operator can change the output shape: * `+` and `-` aggregate both inputs to their **common dimensions** (the **intersection** of the shared dimensions) * `*`, `/` and `%` calculate across the **combined dimension set** (the **union** of both inputs’ dimensions) As a rule of thumb: * `+` and `-` keep the **coarser** level in each shared dimension * `*`, `/` and `%` keep the **finer** level in each shared dimension If your output shape matters, make the intended dimensionality explicit before combining nodes, for example with `ROLLUP`, `ROLLUP_TO`, `EXPAND`, or `DROPLEVEL`. ## Operator reference | Operator | Details | Use for | Common patterns | | -------- | --------------------------------------- | ------------------------------------------------------------------------ | ---------------------------- | | `+` | [ADDITION (+)](/addition/) | Sum values | `'Revenue' + 'Other income'` | | `-` | [SUBTRACTION (-)](/subtraction/) | Compute deltas | `'Revenue' - 'COGS'` | | `*` | [MULTIPLICATION (\*)](/multiplication/) | Multiply values | `'Price' * 'Volume'` | | `/` | [DIVISION (/)](/division/) | Calculate ratios | `'Profit' / 'Revenue'` | | `%` | [MOD](/mod/) | Take the remainder of a division, for bucket logic and periodic patterns | `'Period' % 12` | ## When to prefer a function * Use `RATIO('Gross Profit', 'Revenue')` when you want a ratio that keeps only the shared dimensions of both inputs * Use `ADDEACH('Sales', 1)` when you want to add a constant to each value without relying on arithmetic shape behavior * Use `MULTIPLY('Price', 'Volume')`, `DIVIDE('Profit', 'Revenue')` when you need stricter validation and clearer mismatch handling * Use `UNION('Revenue', 'Other income')` when you want to combine result sets while enforcing matching levels and preventing silent overlap ## Pitfalls & troubleshooting * **Wrong shape after** `+` **or** `-`: check whether the inputs were aggregated to their common dimensions before the calculation * **Unexpected expansion after** `*` **or** `/`: check whether the result kept the combined dimension set * **Unexpected level detail**: remember that `+` and `-` keep the coarser shared level, while `*` and `/` keep the finer shared level * **Need stricter mismatch handling**: use validated functions such as `MULTIPLY`, `DIVIDE` or `UNION` * **Sign mistakes**: consider modeling cost positions as negative values and using `+` consistently ## Related * [Formula basics](/formula-basics/): evaluation order, constants, and quoting rules * [Dimensionality & hierarchies](/dimensionality-hierarchies/): functions for explicit shaping * [Troubleshooting guide](/troubleshooting-guide/): wrong shape, wrong numbers, and empty output --- # Assumption Categories URL: https://docs.valsight.ai/assumption-categories/ Description: Assumption Categories help structure assumptions in the Scenario Manager, making it easier to filter, organize, and analyze assumptions effectively. This fea… Assumption Categories help structure assumptions in the **Scenario Manager**, making it easier to **filter, organize, and analyze assumptions** effectively. This feature replaces the previous “Assumption Properties” functionality, providing a **more intuitive and accessible** way to categorize assumptions. ![image-20250304-092348.png](./images/5986648068.png) Admins can now create assumption categories directly in the user interface. Each assumption category can have predefined **values**, allowing users to **tag assumptions** with relevant labels such as priority levels, statuses, or assumption types. ## Key benefits of Assumption Categories * **Improved organization**: Categorize assumptions with custom labels for better structure. * **Enhanced filtering**: Easily focus on relevant assumptions in the Scenario Manager. * **Customizable properties**: Define assumption categories and values that fit your project needs. ## How to create and manage Assumption Categories ### 1. Creating an assumption category 1. **Navigate to the Assumption Categories page**: * Open the **Scenario Manager**. * Click on **+ Add** → **Configure Assumption Categories**. * Alternatively, go to **Project Settings** and click **Configure Assumption Categories** under the Assumption Categories section. ![image-20250304-104823.png](./images/5985796131.png) 2. **Add a new category**: * Click **Add Category**. * Enter a **name**. It must not be empty, must be at most 255 characters, must be unique within the project, and must not collide with a level name in the project or with an aggregation keyword (SUM, AVG, MIN, MAX, OPENINGSUM, OPENINGAVG, CLOSINGSUM, CLOSINGAVG). There is no special-character rule. * (Optional) Add a **description** to clarify the category’s purpose. * Click **Save** to create the category. ![image-20250304-104857.png](./images/5986058251.png) ### 2. Adding values to a category 1. Open an **existing assumption category**. 2. Click **Add Value**. 3. Enter a **value name** (e.g., "High", "Medium", "Low"). 4. Select a **color** for better visualization. 5. (Optional) Set a **default value** (this will be preselected when tagging assumptions). 6. Click **Save**. ![image-20250304-105025.png](./images/5986254878.png) ### 3. Editing or deleting categories and values * Click the **three-dot menu** next to a category or value to **edit** or **delete** it. * Deleting a category will remove it from all associated assumptions (confirmation required). ![image-20250304-105141.png](./images/5985959953.png)![image-20250304-105213.png](./images/5986615305.png) ## Using Assumption Categories in the Scenario Manager * Once categories and values are set up, users can **assign them** to assumptions. * Categories appear as **sortable and filterable columns** in the **Scenario Manager**. * Values are displayed as **colored tags**, making it easy to differentiate assumptions. ## Additional notes * **Project Admins** can create and modify assumption categories. * Categories and values are stored at the **project level**. * Changing the order of categories **affects bridge calculations** and may alter scenario results. --- # Assumption Effects URL: https://docs.valsight.ai/assumption-effects/ Description: How the effect of a single assumption is calculated, how to show it in a chart or table, and how to display an assumption's description on hover. A central workflow when working with assumptions is to see what an individual assumption does to your plan. There are two ways to look at that: a [bridge](/bridges/), which explains a whole difference as a chain of assumption effects, and an ordinary chart or table set to show the effect of the assumptions you pick. ## How the effect is calculated The effect of an assumption is the delta between two calculations of the same scenario: * the selected scenario **with** the assumption * the selected scenario **without** it It does not matter whether the assumption is actually active in the scenario you selected. The calculated effect is the same either way, because both sides of the delta are computed for you. What does change the number is which scenario you select. Assumptions interact, so the effect of one assumption depends on which others are in play around it. These cross-effects mean the same assumption can legitimately show a different value in two different scenarios. On a bridge you decide how that interaction is shown. **Cross effects**, in the **Advanced Formatting** section of the chart editor, offers three options: | Option | What the bridge shows | | ------------ | ----------------------------------------------------------------------------------------- | | **Total** | One combined bar for all cross-effects together. | | **None** | No cross-effect bar at all. | | **Detailed** | One bar per interaction, so you can see which assumptions are working against each other. | ## Showing assumption effects in a chart or table **Show Assumption Effects** can be switched on for any chart, which lets you display the effects using line charts, bar charts or tables rather than a bridge. At least one assumption has to be selected for it to show anything. ![The Show Assumption Effects option in the chart editor](./images/5148377144.png) * The chart displays the effect of the assumptions you selected. * The subtitle of the chart notes that you are looking at the individual effect of an assumption, rather than at the values themselves. ## Showing assumption descriptions An assumption can carry a custom description, and a bridge can show it when a reader hovers over that assumption's bar. This saves explaining each step out loud when presenting. ![A bridge showing an assumption's description in a tooltip on hover](./images/5751046209.png) To set one up: 1. Click an assumption's name to open its settings. ![The settings of an assumption, opened by clicking its name](./images/5751046215.png) 2. Write the text in the **description** box. 3. Select the chart and switch on **Show descriptions in tooltips** in the chart inspector. ![The Show descriptions in tooltips setting in the chart inspector](./images/5751046221.png) This works the same way in [scenario bridges](/scenario-bridges/) and [time bridges](/time-bridges/). ## Related * [Bridges](/bridges/): the two bridge types, which show these effects as a staircase. * [Grouping Assumption Effects](/grouping-assumption-effects-in-bridges/): combine the line-items of one assumption into a single bar. * [Scenario Bridges](/scenario-bridges/): explain a difference between scenarios. * [Time Bridges](/time-bridges/): explain a difference between periods. --- # Assumption Templates URL: https://docs.valsight.ai/assumption-templates/ Description: When Creating Assumptions you always have a specific case in mind that you want to capture with this Assumption. Such cases follow certain logics and typical… When Creating Assumptions you always have a specific case in mind that you want to capture with this Assumption. Such cases follow certain logics and typically have similar patterns. Assumption Templates allow you to pre-define such a pattern and start with a Use-Case specific foundation when creating a new Assumption. ## Creating assumptions from templates ![image-20230531-095543.png](./images/5148147750.png) If you have configured Assumption Templates, you will be able to choose the template to use when clicking on the 'Add Assumption' button. The dialog will show you a list of all existing Templates on the Model of your workspace including details like * **Name and description** give you a first understanding of the intended Use-Case for the Assumption Template. * **Filter levels** indicate which Filters you can set when creating an Assumption using this Template. After choosing the Template, the dialog will guide you step by step to set each Filter. For each Filter you can choose to select all values or only a subset. We strongly advise to always select the minimal amount of values to improve performance and make the data entry as simple as possible. * **Line-Items** show you the individual Line-Items included in the Assumption Template. When creating the Assumption you can choose if all Line-Items or only a subset shall be included in your newly created Assumption. ## Defining assumption templates To create templates you first define a normal Assumption (Creating Assumptions) in the Scenario Manager and add all the required Line-Items. Once you have your Assumption ready, open the context menu and press 'Save as Template'. ![Screenshot 2023-03-24 at 11.54.44.png](./images/5102501897.png) This will open the Assumption Template create dialog, where you can specify a name and description for your Template. Try to pick a meaningful name that clearly states the intention of the Template and add a brief description. If required, you can choose to update an existing Template - this will delete the old Template and replace it with the newly created one. ![Screenshot 2023-03-24 at 11.55.03.png](./images/5101322450.png)![Screenshot 2023-03-24 at 11.55.11.png](./images/5101912113.png) In a second step, you can decide if you want the selection of line-items to be enabled later when an Assumption is created, and you can also choose the Filters, that should be customized when an Assumption is created using your Template. We advise to select the maximum number of Filters to give users the option to customize their Assumption as much as possible when using your Template. If you do not select a Filter, the created Assumptions will copy the configured Filters for this Dimension if they exist. The Filters are only applied to Line-Items that are available on the respective Dimensions. --- # Assumption Versioning URL: https://docs.valsight.ai/assumption-versioning/ Description: When creating a new version of an Assumption, you save the Assumption with all its properties as well as all the Line-Items attached to it. When creating a new version of an Assumption, you save the Assumption with all its properties as well as all the Line-Items attached to it. When restoring a version, all changes which have been made since the creation of the version will be reverted, including all changes to Line-Items. Please make sure you create a current version of your Assumption if you wish to save those. ## Create new versions of assumption Open the *Scenario Manager* and select the *options* (3 dots) next to the Assumption you want to version. Select *Versioning → Save Version* to save the current state of the Assumption. ![Screen Shot 2019-02-18 at 13.33.29.png](./images/5094190237.png) Now you can name the new Assumption version and provide a description if you chose to do so. Hit *Confirm* to save the Assumption Version. ![Screen Shot 2019-02-18 at 13.33.48.png](./images/5094190242.png) ## Restore an assumption version Open the *Scenario Manager* and select the O*ptions* (3 dots) next to the Assumption you want to restore. Select *Show History* to open all saved Assumption Versions. Now select the version you want to restore and choose *Restore to selected version*. ![Screen Shot 2019-02-18 at 13.34.30.png](./images/5094190172.png) ## Restoring assumptions with Line-Item variants Versioning Assumptions **includes** all **Line-Items** and all **Line-Item Variants.** When restoring Assumptions that include Variants, the restored Variants will override all currently existing Variants. ## Deleting assumption versions Select *Show History* to open the *Assumption Version History* dialog, tick the versions you want to remove and use the **Delete** button in its footer. Valsight checks where those versions are used before deleting anything, which gives three outcomes: 1. **A shared version cannot be deleted.** Valsight names them: ‘You selected currently shared version(s), which cannot be deleted. You should unshare the following version(s) before retrying to delete: …’. 2. **Dependent versions go with it.** If other versions refer to the one you selected and are not used anywhere else, they are listed under ‘Proceeding will also cause the automatic deletion of the dependent version(s) as detailed below’ and are removed together with your selection. 3. **Versions still in use elsewhere block the deletion.** ‘You cannot delete versions that are still in use elsewhere in the project.’ Clear those dependencies first, then retry. > Deleting a version cannot be undone. The dialog says as much before you confirm with **I am sure. Please delete!** This is the same flow [Scenario Versioning](/scenario-versioning/) describes for scenario versions. --- # Assumptions URL: https://docs.valsight.ai/assumptions/ Description: Assumptions represent explicit views on how the future might develop. They capture planned or discussed changes and apply them consistently across the model … Assumptions represent **explicit views on how the future might develop**. They capture planned or discussed changes and apply them consistently across the model to explore alternative outcomes. ## Why are they relevant * For planning or discussing possible future developments * When a change affects multiple values or drivers at once * To group related changes into one coherent idea * To comparing the impact of different measures or viewpoints ## How it works An assumption describes an **encapsulated change on top of the base data**. Each assumption: * Represents one idea or measure (e.g. market growth, cost increase, hiring plan) * Groups all related changes that belong to that idea * Can affect multiple line items and years at once * Exists independently from other assumptions Assumptions make it easy to understand *what changed* and *why*, without having to inspect individual calculations. ![Scenario Manager\_Assumptions.png](./images/6663438366.png) ## Setup Assumptions are created and managed in the Scenario Manager. Once created, they can be reused, combined, or reordered to match planning discussions and priorities. ## Using the feature * Use assumptions to evaluate alternative developments or planned measures. * Group related changes into a single assumption instead of spreading them across the Scenario Manager. * Review an assumption’s impact at a glance with just one click. ## Access & permissions Assumptions follow workspace and scenario permissions. Opening the Scenario Manager only needs view access. Creating and editing assumptions needs **Full Access** on the workspace *and* at least a Simulator user type, so a Basic user with full workspace access still cannot edit them. See [Licenses, User Types & Access Management](/licenses-user-types-access-management/). ## FAQ **What is an assumption in planning terms?** An assumption is a stated view or estimate of how the future might develop. **Can one assumption affect multiple values?** Yes. An assumption typically groups several related changes. **Are assumptions tied to a single scenario?** Assumptions can be reused and combined across scenarios. **Do assumptions replace base data?** No. They apply changes on top of the base data. ## Related * [Working with different Model Baselines](/working-with-different-model-baselines/) * [Line-items](/line-items/) --- # Assumptions & Line-Items URL: https://docs.valsight.ai/assumptions-line-items/ Description: What you will find in this section This section covers the creation and management of assumptions and line-items, including how to create, modify, and organize them, as well as bulk uploading via Excel. --- # Assumptions & result sets URL: https://docs.valsight.ai/assumptions-result-sets/ Description: Use this category when you need to control how assumptions affect a node’s values or when you want to combine result sets. Use this category when you need to **control how assumptions affect a node’s values** or when you want to combine result sets. These functions help you compare results with and without assumptions, append non-overlapping outputs, and support legacy behavior during migration. ## Start here if you want to: * See a node **without assumptions applied** for comparison or debugging * **Combine result sets** from multiple nodes by appending non-overlapping slices * Understand legacy disaggregation logic in older models ## Not here if you want to: * Allocate values down to more detail → see [Dimensionality & hierarchies](/dimensionality-hierarchies/) * Filter to a subset, fill gaps, or rank → see [Filtering & data shaping](/filtering-data-shaping/) ## Mental model * `BASELINE` removes assumptions on the node and upstream * `NONSIM` removes assumptions on the node itself but keeps upstream assumptions * `UNION` combines non-overlapping result sets on the same levels * `DISAGGREGATE` exists for legacy compatibility and should be replaced by `DISTRIBUTE` in new models ## Common patterns | Name | What it does | Formula | | ----------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------- | | Compare against baseline | Use when you want to validate how assumptions affect a result. | `BASELINE('Revenue')` | | Remove assumptions on the node only | Use when you want to isolate assumptions placed on the node itself. | `NONSIM('Revenue')` | | Append disjoint time slices | Use when inputs cover different periods and you want one continuous output. | `UNION('Actuals2024', 'Actuals2025')` | | Use level matching as a guardrail | Use when you want the model to fail fast if level structures diverge. | `UNION('NodeA', 'NodeB')` | | Migrate legacy disaggregation logic | Use `DISAGGREGATE` only for backwards compatibility; prefer `DISTRIBUTE` now. | `DISAGGREGATE` | ## Functions in this category | Function | Description | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------- | | [BASELINE](/baseline/) | Returns the value of a node with no assumptions applied on the node or anywhere upstream. | | [NONSIM](/nonsim/) | Returns a node’s value without assumptions on the node itself while applying assumptions upstream. | | [UNION](/union/) | Combines the result sets of two or more input nodes. | | [DISAGGREGATE](/disaggregate/) | Distributes values of one node onto a level based on another node’s value distribution (legacy; use DISTRIBUTE). | ## Choosing between similar functions **BASELINE vs NONSIM** * Use `BASELINE` to remove assumptions on the node and upstream * Use `NONSIM` to remove assumptions on the node only, while keeping upstream assumptions **UNION vs** `+` * Use `UNION` when you want to append disjoint slices and enforce the same levels with no overlap * Use `+` when you want to combine overlapping values arithmetically **UNION vs reshaping functions** * Use `UNION` to combine result sets from multiple nodes * Use reshaping functions such as `ROLLUP` or `EXPAND` when you want to change granularity or dimensionality **DISAGGREGATE vs DISTRIBUTE** * Use `DISAGGREGATE` only for legacy compatibility * Use `DISTRIBUTE` for new models and ongoing development ## Pitfalls & troubleshooting * **Baseline looks “too different”:** verify where assumptions are applied (on the node vs upstream) and choose `BASELINE` vs `NONSIM` accordingly * **UNION fails because levels don’t match:** confirm both inputs have the exact same level set * **UNION fails because rows overlap:** ensure the same intersection does not exist in more than one input; split inputs into disjoint slices, or use `+` if overlap is intended * **Legacy function in active use:** if you still rely on `DISAGGREGATE`, plan migration to `DISTRIBUTE` to avoid legacy limitations and reduce maintenance risk ## Related * [Operators](/operators/): using `+` when overlap in `UNION` is intended * [Dimensionality & hierarchies](/dimensionality-hierarchies/): `DISTRIBUTE` and shaping before combining * [Filtering & data shaping](/filtering-data-shaping/): reduce result sets before combining * [Troubleshooting guide](/troubleshooting-guide/): assumptions, missing values, unexpected results --- # Available Logs URL: https://docs.valsight.ai/available-logs/ Description: All log files are stored in the logs/ directory. All log files are stored in the logs/ directory. | Logfile | Content | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | | access.log | All HTTP requests to the application. Includes the username for authenticated users. | | error.log | Debug info and stacktraces for all failed requests. | | application.log | Regular warnings and Execution log of the application. Contains query runtime information. Failed Login Attempts are logged here. | | security audit log | [Security audit log](/security-audit-log/) | --- # Axis Scales and Decimals URL: https://docs.valsight.ai/axis-scales-and-decimals/ Description: Set the scale size, decimal places and value range of each axis in a chart, and add a second axis for nodes with a different unit. How large the numbers on an axis look, how many decimals they carry and where the axis starts and ends are all set per axis, not per chart. ## What it is The default scale size and number of decimal places follow the unit and your system configuration, and can be overridden per chart. With a scale size of millions, 3,480,000 euros is shown as 3.5. A chart can have several axes. That is what lets it display nodes with different units, for example one node in euros and one in percent, each against its own axis. ## When to use it * The numbers are too long to read and a scale of thousands or millions would do. * The chart mixes units and the second unit needs its own axis. * You want every chart on a sheet to start and end at the same value so they can be compared at a glance. To give one node the same scale everywhere it is charted rather than fixing it per chart, see [Default Scale Settings in Nodes](/default-scale-settings-in-nodes/). ## Configuration 1. Select the chart. The chart editor opens on the right. 2. Scroll to the **Formatting** section and click **Scales and Digits**. 3. Pick the axis tab you want to change, or add one with **Add Axis**. 4. Set the values below, then click **Save**. **Delete Axis** removes an axis you have added. | Setting | What you get | | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | **Scale Size** | The factor the values are shown in, for example millions. **Auto** follows the unit and your system configuration. | | **Decimal Places** | How many decimals the values carry, from 0 to 5. Leave it empty for **Auto**. Typing more than 5 is refused with a warning. | | **Min Value**, **Max Value** | Where the axis starts and ends. **Auto** picks values that use the available space well. | | **Invert Axis** | Turns the direction of the axis around. | | **Show Y-Axis Breaks** | Draws the axis with a break in it instead of one continuous range. See [Y-Axis Breaks in Charts](/y-axis-breaks-in-charts/). | ![The Scales and Digits dialog, with scale size, decimal places, value range and axis options](./images/scales-and-digits.png) ## Good to know * **The scale applies to the whole axis.** When a chart mixes nodes of very different magnitudes, one axis scale cannot suit all of them, and raising it rounds the small values to zero. Set the scale per node instead: see [Default Scale Settings in Nodes](/default-scale-settings-in-nodes/). * **Rescaling is not the only way to fit a wide range.** To keep small differences visible without touching the scale, break the axis: see [Y-Axis Breaks in Charts](/y-axis-breaks-in-charts/). * **Show Y-Axis Breaks is off limits with several axes.** On a chart with more than one axis the toggle is disabled: see [Y-Axis Breaks in Charts](/y-axis-breaks-in-charts/). * **Each axis carries its own data series.** Moving a node to a second axis changes which axis its values are read against, not the values themselves. ## Related * [Default Scale Settings in Nodes](/default-scale-settings-in-nodes/): one scale for a node, everywhere it is charted. * [Y-Axis Breaks in Charts](/y-axis-breaks-in-charts/): cut a large value range instead of rescaling it. --- # Backup & Recovery URL: https://docs.valsight.ai/backup-recovery/ Description: ON PREMISE This article applies only to Valsight On-Premise. Contact support for Cloud installations. **ON PREMISE** This article applies only to Valsight On-Premise. Contact support for Cloud installations. ## Backup A complete backup of the application consists of: * Complete database * conf/ directory for the database configuration * Installation Files & License file All user data is part of the database dump, Valsight does not store additional user files in its working directory. ## Recovery To recover a previous backup: * Drop & recreate the database from the backup * restore the configuration * make sure that the installation matches the version of the backup and that the license file is in the right place ## Examples ### Postgresql #### Backup ``` pg_dump es-rest-service | bzip2 -c > “backup.sql.bz2“ ``` #### Recovery ``` dropdb es-rest-service ``` ``` createdb -O grails es-rest-service ``` ``` bunzip –c backup.sql.bz2 | psql es-rest-service ``` --- # BASELINE URL: https://docs.valsight.ai/baseline/ Description: Returns the value of a node with no assumptions applied, removed from the referenced node and all upstream nodes that affect it. **Category:** [Assumptions & result sets](/assumptions-result-sets/) ## Overview The **BASELINE** function **returns the value of a node with no assumptions applied**. Assumptions are removed from the referenced node and all upstream nodes that affect it. Use this function to compare the effect of assumptions by seeing what a node's value would be without them. ## Syntax `BASELINE('Node' [, "useVariablesFrom"])` **Example usage:** `BASELINE('Revenue')` ## Parameters | Parameter | Description | Type | Required | Default | | -------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ------------ | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | -- | | **useVariablesFrom** | Determines which variable values are used in the calculation | Keyword | No | `"SCENARIO"` | **useVariablesFrom options:** * `"SCENARIO"`: Uses variable values as overridden by the scenario. This is the default. * `"PROJECT"`: Uses the original project default values instead of scenario overrides. ## Output shape | Aspect | Behavior | | -------------- | --------------------------------------------------------------------------------------------- | | Dimensionality | Same as the input node. | | Values | The input node's values computed without any assumptions applied to it or its upstream nodes. | | Row count | Same as the input node's baseline values. | ## Watch out * The input must be a **single node reference**. Combinations of operations (e.g. `'A' + 'B'`) are not valid. * If the model has **multiple baselines**, the baseline of the current scenario is used. * The **PROJECT** mode only applies project default variable values to nodes calculated within the BASELINE function. Upstream nodes outside the BASELINE call still use scenario variable values. * BASELINE removes assumptions from the node **and all upstream nodes**. To remove assumptions from only the specified node while keeping upstream assumptions, use [NONSIM](/nonsim/) instead. ## Examples ### Baseline values without assumptions This example shows the baseline result of multiplying two nodes when no assumptions or variable overrides are applied. The project default variable $MY\_VAR is set to 10. **Project default variables:** $MY\_VAR = 10 **Input node:** `'Node 1'` | Year | Value | | ---- | ------------- | | 2025 | $MY\_VAR = 10 | | 2026 | $MY\_VAR = 10 | | 2027 | $MY\_VAR = 10 | | 2028 | $MY\_VAR = 10 | **Input node:** `'Node 2'` | Year | Value | | ---- | ----- | | 2025 | 1 | | 2026 | 1 | | 2027 | 1 | | 2028 | 1 | **Formula:** `'Node 1' * 'Node 2'` | Year | Value | | ---- | ----- | | 2025 | 10 | | 2026 | 10 | | 2027 | 10 | | 2028 | 10 | These are the baseline results with no assumptions applied. ### Values with scenario overrides and assumptions This example shows how the same nodes look when a scenario overrides $MY\_VAR to 20 and assumptions are activated on both nodes. **Variable override via scenario:** $MY\_VAR = 20 **Input node:** `'Node 1'` (with overridden $MY\_VAR as 'Base' and activated assumptions as 'Change') | Year | Base | Change | Result | | ---- | ---- | ------ | ------ | | 2025 | 20 | 0 | 20 | | 2026 | 20 | 10 | 30 | | 2027 | 20 | 20 | 40 | | 2028 | 20 | 30 | 50 | **Input node:** `'Node 2'` (with the initial measures as 'Base' and activated assumptions as 'Change') | Year | Base | Change | Result | | ---- | ---- | ------ | ------ | | 2025 | 1 | 1 | 2 | | 2026 | 1 | 2 | 3 | | 2027 | 1 | 3 | 4 | | 2028 | 1 | 4 | 5 | **Formula:** `'Node 1' * 'Node 2'` | Year | **Base** (Node 1 × Node 2) | Change | Result | | ---- | -------------------------- | ------ | ------ | | 2025 | 20 × 2 | 5 | 45 | | 2026 | 30 × 3 | 5 | 95 | | 2027 | 40 × 4 | 5 | 165 | | 2028 | 50 × 5 | 5 | 255 | ### Comparing SCENARIO vs PROJECT mode This example shows the difference between the two modes: SCENARIO uses the variable value overridden by the scenario (20), while PROJECT uses the original project default (10). **Formula:** `BASELINE('Result Node')` **Equivalent to:** `BASELINE('Result Node', "SCENARIO")` | Year | BASELINE Result | | ---- | --------------- | | 2025 | 20 | | 2026 | 20 | | 2027 | 20 | | 2028 | 20 | BASELINE removes all assumptions but keeps the scenario's variable override ($MY\_VAR = 20). **Formula:** `BASELINE('Result Node', "PROJECT")` | Year | BASELINE Result | | ---- | --------------- | | 2025 | 10 | | 2026 | 10 | | 2027 | 10 | | 2028 | 10 | PROJECT mode also reverts the variable to its project default ($MY\_VAR = 10). ## Related | Function | When to use instead | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [NONSIM](/nonsim/) | When you only want to remove assumptions from the node itself. BASELINE removes assumptions from the node and all upstream nodes; NONSIM only removes them from the specified node. | --- # Baseline Indicator on Nodes URL: https://docs.valsight.ai/baseline-indicator-on-nodes/ Description: When a node has "Operation per Baseline" enabled, an indicator icon appears next to the node's warnings area to show whether the baselines are actually produ… When a node has "Operation per Baseline" enabled, an indicator icon appears next to the node's warnings area to show whether the baselines are actually producing different results. ![Operations per baseline icon.png](./images/6884818945.png) ## How to enable Two settings must be active for the indicator to appear: 1. In the **Node Editor**, open **Advanced Settings** and turn on the **Operation per Baseline** toggle. 2. In the **Model** tab of the Editor, go to **Layout → Node Display** and turn on the **Show Baseline Indicators** toggle. ![Show Baseline Indicators highlight.png](./images/6884950020.png) --- # Baselines URL: https://docs.valsight.ai/baselines/ Description: This guide shows you how to create a new baseline in a project so that it becomes available across all models in that project. This guide shows you how to create a new baseline in a project so that it becomes available across all models in that project. ## Prerequisites * You have admin access to the project. ## Steps ### Open Project Settings Open **Project Settings** for the project. ### Go to the baselines section Navigate to the **Baselines** section and click **Configure baselines**. ### Add a new baseline Click **Add** to add a new baseline. ### Name the baseline Enter a **name** for the baseline. The name must be unique within the project. ### Add a description and color (optional) Enter a **description** to help other users understand the purpose of this baseline, and select a **color** to visually distinguish it in the Model Editor. ### Save Click **Save** to confirm. Video: [Create new baseline](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6896910343_Create-new-baseline.mov) ## What you have done The new baseline is now available across all models in the project. Model builders can reference it when configuring nodes with baseline-specific operations. ## Limitations * **The name is already in use**: Each baseline name must be unique within the project. Choose a different name and try again. * **The "Data" baseline cannot be deleted**: "Data" is the default project baseline and is permanently available. It can be renamed but not removed. * **Deleting a baseline removes its formulas**: deleting a baseline also removes every baseline-specific formula that referenced it, across all models in the project. The dialog says so, and the action cannot be undone. * **A baseline still in use cannot be deleted**: deletion is refused while any scenario uses the baseline, and while the nodes referencing it are locked by someone else. * **System baselines cannot be deleted**: baselines tagged **System Baseline** in the baseline list have Delete disabled. ## Related * [Baseline Indicator on Nodes](/baseline-indicator-on-nodes/) --- # Best practices for dimensions URL: https://docs.valsight.ai/best-practices-for-dimensions/ Description: Designing a dimension means choosing the right levels and the right granularity for your analysis. Designing a dimension means choosing the right levels and the right granularity for your analysis. Use this page when you design or refactor a dimension. The Requirements section lists what Valsight enforces; Design principles covers what makes the dimension easier to maintain. ## Requirements ### Dimensions must be MECE Each level of a hierarchy must be **mutually exclusive and collectively exhaustive** ([MECE](https://en.wikipedia.org/wiki/MECE_principle)): * **Mutually exclusive**: every data point belongs to exactly one entry on a given level; no value can appear under two parents at the same time. * **Collectively exhaustive**: every data point belongs to *some* entry on the level; no value can be left without a parent. If a value cannot be cleanly placed under one of your existing parents, you have either defined the level wrong or you need a "catch-all" parent to absorb the remainder. #### Example: a regional hierarchy The **Location** dimension has three levels: **Total**, **Region**, **Country**. The Region level groups countries into *EMEA*, *America*, and *Rest of World*, with *GER* and *FRA* under EMEA, *USA* under America, and *JPN*, *IND*, *AUS* under Rest of World. ![image-20260521-115034.png](./images/7005241390.png) This hierarchy is MECE: * **Mutually exclusive**: each country has exactly one Region parent. If GER were listed under both EMEA and Rest of World, that would be a mutual exclusivity violation. * **Collectively exhaustive**: every country has a home. If JPN, IND, and AUS were left out of the hierarchy, their data would appear missing. The *Rest of World* bucket is the catch-all that keeps every country represented at the Region level. ### Level names must be unique across the project Two dimensions in the same project cannot share a level name. Valsight enforces this in the software and on Excel upload; an uploaded column that reuses a level name from another dimension produces a validation error (see [Excel upload feedback messages](/excel-upload-feedback-messages/)). > **Do not name your own levels ‘Week’, ‘Month’ or ‘Quarter’.** The system [Time dimension](/time-dimension/) is exempt from the rule above, so Valsight will let you create a level with one of those names. It then blocks switching the project's calendar between months and ISO weeks, because the switch would have to create a Time level whose name is already taken. ## Design principles These are recommendations, not enforced rules. Following them makes a dimension easier to maintain and reason about. * **Don't model finer than you need.** Excessive granularity inflates cube sizes, slows calculations, and adds maintenance burden for no analytical gain. Decide the level of detail your analysis actually requires before designing the dimension. * **Pick the lowest level first.** Once you have settled on the right level of detail, design the dimension from that level upward. Reverse-designing from the top usually leaves gaps. * **Name levels by what they contain, not how they roll up.** "Country" is better than "Region detail". * **Avoid placeholder values like "Other" or "Unknown" on a granular level.** They usually signal that the upper levels are not collectively exhaustive (a MECE violation). Add a real catch-all parent instead. ## Limitations * Each dimension must be updated separately. You cannot update multiple dimensions in a single Excel upload. * When updating via Excel, the full structure must be supplied. Partial uploads are not supported. * Levels used as level links to other dimensions cannot be removed via Excel. Remove the link first. ## Related * [How dimensions work](/how-dimensions-work/): the concept and vocabulary * [Creating dimensions](/creating-maintaining-dimensions/): setting up a dimension end to end * [Excel upload feedback messages](/excel-upload-feedback-messages/): validation messages that enforce these requirements --- # Bridges URL: https://docs.valsight.ai/bridges/ Description: A bridge breaks the difference between two values down into the individual effects that produced it, either across time periods or across scenarios. A bridge breaks the difference between two values down into the individual effects that produced it, either across time periods or across scenarios. All bridges use the staircase shape the chart editor calls a **waterfall chart**. ## Start here if you want to: | If you | Go to | | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- | | Explain why one scenario differs from another | [Scenario Bridges](/scenario-bridges/) | | Explain why one period differs from another | [Time Bridges](/time-bridges/) | | Understand how the effect of a single assumption is calculated, or show its description on hover | [Assumption Effects](/assumption-effects/) | | Net an assumption's removed and added contributions into a single bar | [Grouping Assumption Effects](/grouping-assumption-effects-in-bridges/) | | Split the model's own contribution out of its single block | [Data Effects Display in Bridge](/data-effects-display-in-bridge/) | ## Related * [Chart Types](/chart-types/): the other chart types and tiles you can place on a worksheet. * [Formatting Charts](/chart-configuration/): sorting, scales and colors, which apply to bridges too. --- # Browse by category URL: https://docs.valsight.ai/browse-by-category/ Description: Browse by category helps you find the right function when you don't know the exact name yet. Functions are grouped by what they do, so you can start from your modeling goal and drill down to the right reference page. Browse by category helps you find the right function when you don’t know the exact name yet. **Functions are grouped by what they do**, so you can start from your modeling goal and drill down to the right reference page. If you already know the function name, use [All functions (A-Z)](/all-functions-a-z/) instead. ## How to find the right function Start with your goal, then choose the relevant function group: | If you | Go to | | ----------------------------------------------------- | ------------------------------------------------------------ | | Connect uploaded data to nodes | [Data access](/data-access/) | | Calculate or transform numeric values | [Math & numeric](/math-numeric/) | | Apply business rules or conditional logic | [Logical functions](/logical-functions/) | | Filter, pick, rank or fill missing data | [Filtering & data shaping](/filtering-data-shaping/) | | Change the result’s shape or granularity | [Dimensionality & hierarchies](/dimensionality-hierarchies/) | | Project values forward or build cumulative time logic | [Rollforward & time series](/rollforward-time-series/) | | Compare values across time | [Compare periods](/compare-periods/) | | Use finance-specific methods | [Finance functions](/finance-functions/) | | Control assumption effects or combine results | [Assumptions & result sets](/assumptions-result-sets/) | ## Related * [Function catalog](/function-catalog/): hub for A-Z and category navigation * [Operators](/operators/): arithmetic and comparisons used inside formulas * [Formula basics](/formula-basics/): notation, constants, evaluation order --- # Build a service for API_CALL URL: https://docs.valsight.ai/build-an-api-call-service/ Description: Implement an HTTP service that the API_CALL formula function can call from inside a Valsight model calculation. ## Goal You will have an HTTP endpoint that the [API\_CALL](/api-call/) formula function can call during a model calculation, and that returns a result Valsight turns into a node. The examples use Python with FastAPI and pandas. Nothing about the contract is specific to either: it is one JSON POST in and one JSON body out, so any language and framework will do. > **Prerequisites** > > * A Valsight account with administrator permissions > * Network access to your Valsight instance Verify access programmatically before proceeding: `GET {base_url}/api/v1/health` must return HTTP 200 with a valid API key in the `X-API-Key` header. ## Steps ### 1. Understand the contract A model node calls your endpoint like this: ``` API_CALL("https://your-service/optimize", ['Volume', 'Capacity'], ["Country", "Site"]) ``` Valsight POSTs the values of `Volume` and `Capacity`, and expects a cube back on the levels `Country` and `Site`. Your service receives: | Key | Value | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `inputs` | The input nodes, keyed by position in the formula as a string: `"0"`, `"1"`. Each value is a cube. | | `result_levels` | The requested level names. A JSON array since 7.3; one string, for example `"[Country, Site]"`, up to 7.2. See [Read the requested levels](#read-the-requested-levels). | | `message` | The formula's `message` argument, passed through untouched. | | `version` | The formula's `version` argument, passed through untouched. | | `format` | Always `"JSON"`. | | `maximum_mbs_to_return` | The instance's response size limit, as a string. | A cube carries its columns as metadata and its values as rows: ``` { "version": "1", "columnMetadata": [ {"name": "Country", "columnType": "level", "levelId": 118}, {"name": "Site", "columnType": "level", "levelId": 101}, {"name": "measure", "columnType": "measure"} ], "tableMetadata": {"tableType": "FACT", "tableName": "Input 0"}, "rowData": [["DE", "S-100", "1200"], ["DE", "S-101", "900"]] } ``` You must answer with HTTP 200–299 and this envelope: ``` { "response_status": "SUCCESS", "error_message": "", "output": { ... a cube in the same shape ... } } ``` Valsight reads only those three keys. See [API\_CALL](/api-call/) for the full reference. #### Read the requested levels `result_levels` changed shape in 7.3: it is a JSON array from 7.3 onwards, and a single rendered string up to 7.2. Accept both and one service works against every release: ```python def requested_levels(body): levels = body.get("result_levels") # 7.3 and later: a real JSON array if isinstance(levels, list): return [str(name) for name in levels] # up to 7.2: one rendered string, for example "[Country, Site]" if isinstance(levels, str) and levels.startswith("[") and levels.endswith("]"): inner = levels[1:-1].strip() return [part.strip() for part in inner.split(",")] if inner else [] return [] ``` On 7.2 and earlier this cannot be made reliable: a level name may itself contain a comma, and the string form gives you no way to tell that comma apart from the separator. The array form in 7.3 removes the ambiguity, which is why the key changed shape. ### 2. Convert a cube to a DataFrame and back These two helpers are the whole translation layer. Everything else in your service is ordinary application code. ```python import pandas as pd def cube_to_frame(cube, measure_name): """Turn one Valsight cube into a DataFrame with a numeric measure column.""" columns = [column["name"] for column in cube["columnMetadata"]] frame = pd.DataFrame(cube["rowData"], columns=columns) frame = frame.rename(columns={"measure": measure_name}) frame[measure_name] = pd.to_numeric(frame[measure_name], errors="coerce") return frame def frame_to_cube(frame, level_names, measure_column, source_cube, table_name): """Turn a DataFrame back into the cube Valsight expects in `output`.""" by_name = {column["name"]: column for column in source_cube["columnMetadata"]} metadata = [ by_name.get(name, {"name": name, "columnType": "level"}) for name in level_names ] metadata.append({"name": "measure", "columnType": "measure"}) ordered = frame[level_names + [measure_column]] return { "version": 1, "columnMetadata": metadata, "tableMetadata": {"tableType": "FACT", "tableName": table_name}, "rowData": ordered.values.tolist(), } ``` Two details in there earn their place: * `pd.to_numeric` is not optional. **Every value in `rowData` arrives as a string**, numbers included. * `frame_to_cube` copies `columnMetadata` from an input cube rather than writing its own. Those entries carry the `levelId` values Valsight uses to map values back onto its dimensions; an invented id fails the conversion. On the way out you may return real JSON numbers. There is no need to turn your results back into strings. ### 3. Start with an echo endpoint Wire up the simplest possible endpoint first. It proves the allow-list, the network path and the envelope are right, with no modelling questions attached. ```python from fastapi import FastAPI, Request app = FastAPI() @app.post("/echo") async def echo(request: Request): body = await request.json() cube = body.get("inputs", {}).get("0") if cube is None: return failure("No input cube received at position 0.") return {"response_status": "SUCCESS", "error_message": "", "output": cube} ``` Call it from a model with `API_CALL("https://your-service/echo", ['Some Node'], ["Year"])`. The node should show the input node's own values. ### 4. Report errors so the user can see them Return HTTP 200 with `response_status` set to `ERROR`, not a 4xx status: ```python def failure(message): return { "response_status": "ERROR", "error_message": message, "output": None, } ``` On a status outside 200–299 Valsight discards the body and shows a generic transport error, so your text never reaches the user. With `ERROR` it is displayed on the node, which is where the person who wrote the formula will look. ### 5. Handle the four cases that actually occur These are the ones that turn up in real models rather than in tests. | Case | What to do | | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | The input cube is empty | Return an empty cube of the right shape, not an error. A modeller who filtered everything out in a scenario legitimately sends nothing, and the node should calculate to zero. | | The solver drops rows | Return the dropped members at `0` rather than leaving them out. A missing row reads as no value, so downstream nodes fall back to a previous figure instead of registering the change. | | A requested level is not in the cube | Fail with a clear `error_message` naming the level. Returning a cube of the wrong shape is far harder to diagnose from inside a model. | | The cube carries levels you did not ask for | Ignore them. Input nodes are sent with **full dimensionality**, so a node on `Site` also arrives with its `Country` column. Read levels by name. | ### 6. Get the endpoint allow-listed API\_CALL refuses every URL until an administrator sets `featureFlags.apiCall.allowedUrlsRegex` on the instance — a Java regular expression that your endpoint must match. Empty is the default and allows nothing. Two other instance limits are worth knowing before you design the payload: | Setting | Default | Meaning | | ------------------------------------- | -------- | ---------------------------------------------------------- | | `featureFlags.apiCall.maxRowsToSend` | `150000` | Maximum rows across all input nodes combined, per request. | | `featureFlags.apiCall.maxMbsToReturn` | `24` | Maximum response size read, in megabytes. | Requests can additionally be restricted to the instance's outbound IP address. Ask your Valsight support team to set both up. ### 7. Keep it fast The default `timeout` is 30 seconds, set per formula. Aim far below it: the node recalculates on every user interaction, so anything past roughly two seconds makes the model feel unresponsive long before the timeout matters. If the underlying computation is genuinely slow, that is a sign the work belongs in an uploaded data table via [DATA](/data/) rather than in a live call. ## Verify Test the endpoint before pointing a model at it. The request body is plain JSON, so no Valsight instance is needed: ```bash curl -s localhost:8000/optimize \ -H 'Content-Type: application/json' -d '{ "format": "JSON", "version": "1", "message": "", "maximum_mbs_to_return": "24", "result_levels": "[Country, Site]", "inputs": { "0": { "version": "1", "columnMetadata": [ {"name": "Country", "columnType": "level", "levelId": 118}, {"name": "Site", "columnType": "level", "levelId": 101}, {"name": "measure", "columnType": "measure"} ], "tableMetadata": {"tableType": "FACT", "tableName": "Input 0"}, "rowData": [["DE","S-100","1200"],["DE","S-101","900"]] } } }' ``` You are done when all four of these hold: * The response is HTTP 200 and `response_status` is `SUCCESS`. * `output.columnMetadata` names exactly the levels you asked for, plus `measure`. * A node using the formula calculates and shows those values. * Deliberately breaking the service — stopping it, or returning `response_status: "ERROR"` — puts a readable message on the node rather than a generic failure. Check the response envelope programmatically rather than by eye. Save the request body above as `request.json`, then write this checker to `check_response.py`: ```python import json, sys r = json.load(sys.stdin) assert r["response_status"] == "SUCCESS", r.get("error_message") cols = [c["name"] for c in r["output"]["columnMetadata"]] assert cols[-1] == "measure", cols print("ok", cols, len(r["output"]["rowData"]), "rows") ``` Run it against the endpoint: ```bash curl -s localhost:8000/optimize -H 'Content-Type: application/json' \ -d @request.json | python3 check_response.py ``` Exit code 0 means the envelope and the cube shape are valid. Exit code 1 prints the service's own `error_message`, which is the same text a user would see on the node. A non-2xx HTTP status is a failure regardless of the body, because Valsight does not read the body at all in that case. Check it separately: ```bash curl -s -o /dev/null -w '%{http_code}\n' -X POST localhost:8000/optimize \ -H 'Content-Type: application/json' -d @request.json ``` ## The complete service Everything above, assembled into one file that runs as it stands. Save it as `valsight_api_call_example.py`, install `fastapi`, `uvicorn` and `pandas`, and start it with `uvicorn valsight_api_call_example:app --port 8000`. Only `solve()` is about the problem. Replace it with a call to your own service and leave the rest — that is the Valsight-facing boilerplate this page has been building up. ```python """ Valsight API_CALL — reference service (FastAPI) ============================================== A Valsight model node can call an external HTTP service in the middle of a calculation and use the response as a node: API_CALL("https://your-service/optimize", ['Volume', 'Capacity'], ["Country", "Site"]) \\______________ ______________/ \\_________ ________/ \\________ _______/ \\/ \\/ \\/ endpoint (allow-listed) input nodes -> "inputs" levels you must return Valsight POSTs one JSON body, expects one JSON body back, and turns the `output` cube into the node's value. That is the whole contract. This file is a runnable reference implementation. Replace `solve()` with a call to your own service — everything around it is the Valsight-facing boilerplate. pip install "fastapi[standard]" pandas uvicorn valsight_api_call_example:app --host 0.0.0.0 --port 8000 Verified against the Valsight product code (OlapApiCallCubeDefinition.groovy) on 2026-08-28, release 7.2. THE REQUEST BODY Valsight sends ------------------------------- { "inputs": { # one entry per input node, keyed by its "0": {}, # position in the formula, as a STRING "1": {} }, "result_levels": ["Country", "Site"], # array from 7.3 on; up to 7.2 # the string "[Country, Site]" "message": "free text", # the formula's `message` argument "version": "1", # the formula's `version` argument "format": "JSON", "maximum_mbs_to_return": "24" # a string, from an instance setting } A cube looks like this. Note that **every value in `rowData` is a string**, numbers included: { "version": "1", "columnMetadata": [ {"name": "Country", "columnType": "level", "levelId": 118}, {"name": "Site", "columnType": "level", "levelId": 101}, {"name": "measure", "columnType": "measure"} ], "tableMetadata": {"tableType": "FACT", "tableName": "Input 0"}, "rowData": [["DE", "S-100", "1200"], ["DE", "S-101", "900"]] } Three things that surprise people: 1. Values are strings. Always `pd.to_numeric(..., errors="coerce")`. 2. Cubes arrive with **full dimensionality**. If the input node is dimensioned on Site only, but Site sits under Country, you still receive a Country column. That is the only channel through which Valsight communicates dimensionality, so read the levels you need by name and ignore the rest. 3. `result_levels` changed shape in 7.3, from a rendered string to a JSON array. Up to 7.2 it cannot be parsed reliably, because a level name may itself contain a comma. `requested_levels()` below reads either form. THE RESPONSE BODY Valsight expects ---------------------------------- { "response_status": "SUCCESS", # or "ERROR" "error_message": "", # shown to the user when status is ERROR "output": {} # same shape as an input cube } Valsight reads only `response_status`, `error_message` and `output`; any other key is ignored. The HTTP status must be in 200-299, otherwise the calculation fails before the body is even looked at. On the way in every value is a string; on the way out you may return real JSON numbers. No need to stringify what you computed. `output` must carry exactly the levels that were requested, plus the `measure` column. Reuse the input cube's `columnMetadata` for those levels rather than writing your own — see `level_metadata()`. LIMITS AND TIMEOUTS ------------------- * Default timeout is 30 s, set per formula via the `timeout` argument. A node is recalculated on every user interaction, so in practice aim well under ~2 s or the model stops feeling interactive. * Max rows sent: 150 000 by default, counted as the **sum over all** input cubes. * Max response read: 24 MB by default. * The endpoint must match the URL allow-list on the Valsight instance (`featureFlags.apiCall.allowedUrlsRegex`) and can be locked to your source IP. Both are set by a Valsight administrator. """ from __future__ import annotations import logging from typing import Any, Dict, List import pandas as pd from fastapi import APIRouter, FastAPI, Request logger = logging.getLogger("valsight.api_call") PAGE = APIRouter() # Levels this service knows how to work with. Keep the interface generic: read # levels by name, pass through what you do not need. SITE_LEVEL = "Site" MEASURE = "measure" # --------------------------------------------------------------------------- # Valsight cube <-> pandas # --------------------------------------------------------------------------- def cube_to_frame(cube: Dict[str, Any], measure_name: str) -> pd.DataFrame: """Turn one Valsight cube into a DataFrame with a numeric measure column.""" columns = [column["name"] for column in cube["columnMetadata"]] frame = pd.DataFrame(cube["rowData"], columns=columns) frame = frame.rename(columns={MEASURE: measure_name}) frame[measure_name] = pd.to_numeric(frame[measure_name], errors="coerce") return frame def level_metadata(cube: Dict[str, Any], level_names: List[str]) -> List[Dict[str, Any]]: """Reuse the input cube's column metadata for the levels we return. Copying it is deliberate: the metadata carries `levelId`, which Valsight uses to map values back onto its own dimensions. Inventing an id here would fail the conversion, so we look each level up and only fall back to a name-only entry when the input did not carry it. """ by_name = {column["name"]: column for column in cube["columnMetadata"]} return [ by_name.get(name, {"name": name, "columnType": "level"}) for name in level_names ] def frame_to_cube( frame: pd.DataFrame, level_names: List[str], measure_column: str, source_cube: Dict[str, Any], table_name: str, ) -> Dict[str, Any]: """Turn a DataFrame back into the cube Valsight expects in `output`.""" metadata = level_metadata(source_cube, level_names) metadata.append({"name": MEASURE, "columnType": "measure"}) ordered = frame[level_names + [measure_column]] return { "version": 1, "columnMetadata": metadata, "tableMetadata": {"tableType": "FACT", "tableName": table_name}, "rowData": ordered.values.tolist(), } def requested_levels(body: Dict[str, Any]) -> List[str]: """The levels Valsight wants back, from either payload form. `result_levels` changed shape in 7.3: a JSON array from 7.3 onwards, a single rendered string up to 7.2. Accepting both keeps one service working against every release. """ levels = body.get("result_levels") # 7.3 and later: a real JSON array if isinstance(levels, list): return [str(name) for name in levels] # up to 7.2: one rendered string, for example "[Country, Site]" if isinstance(levels, str) and levels.startswith("[") and levels.endswith("]"): inner = levels[1:-1].strip() return [part.strip() for part in inner.split(",")] if inner else [] return [] # --------------------------------------------------------------------------- # Response envelope # --------------------------------------------------------------------------- def success(output: Dict[str, Any], function_name: str) -> Dict[str, Any]: return { "format": "JSON", "version": "1", "function_name": function_name, "response_status": "SUCCESS", "error_message": "", "output": output, } def failure(message: str) -> Dict[str, Any]: """Report a business error. Return HTTP 200 with status ERROR, not a 4xx: on a non-2xx Valsight discards the body and shows a generic transport error, so `message` would never reach the user. With status ERROR it is displayed on the node. """ logger.warning("returning ERROR to Valsight: %s", message) return { "format": "JSON", "version": "1", "response_status": "ERROR", "error_message": message, "output": None, } # --------------------------------------------------------------------------- # Endpoint 1 — connectivity check # --------------------------------------------------------------------------- @PAGE.post("/echo") async def echo(request: Request) -> Dict[str, Any]: """Return input cube 0 unchanged. The first thing to wire up: it proves the allow-list, the network path and the envelope are right, without any modelling questions attached. API_CALL("https://your-service/echo", ['Volume'], ["Country", "Site"]) """ body = await request.json() cubes = body.get("inputs", {}) logger.info("/echo keys=%s cubes=%s", list(body), list(cubes)) cube = cubes.get("0") if cube is None: return failure("No input cube received at position 0.") return success(cube, "echo") # --------------------------------------------------------------------------- # Endpoint 2 — the optimizer call # --------------------------------------------------------------------------- def solve(volume: pd.DataFrame, capacity: pd.DataFrame, integer: bool) -> pd.DataFrame: """>>> REPLACE THIS with a call to your own service. <<< Everything above and below is Valsight plumbing; this is the only part that is actually about the problem. Contract: take the input frames, return a frame with the same level columns plus one numeric result column named `optimized`. The placeholder below allocates volume up to a per-country capacity limit, scaling proportionally when demand exceeds it. It exists so the file runs as-is — it is not a model of anything. """ data = volume.merge(capacity, on="Country", how="left") limit = data["capacity"].fillna(float("inf")) demanded = data.groupby("Country")["volume"].transform("sum") scale = (limit / demanded).clip(upper=1.0).fillna(1.0) data["optimized"] = data["volume"] * scale if integer: data["optimized"] = data["optimized"].round() return data @PAGE.post("/optimize") async def optimize(request: Request) -> Dict[str, Any]: """Two input cubes in, one optimized cube out. API_CALL("https://your-service/optimize", ['Volume per Site', 'Capacity per Country'], ["Country", "Site"], "JSON", "1", "continuous", 20) \\________/ \\/ message timeout, seconds The optional arguments are positionally nested in the formula grammar: to pass `timeout` you must also pass `format`, `version` and `message`. """ body = await request.json() cubes = body.get("inputs", {}) # `message` is passed through verbatim, which makes it a convenient mode # switch — you can change solver behaviour from the formula without # touching the API. message = body.get("message") or "" integer = "integer" in message.lower() levels = requested_levels(body) logger.info( "/optimize cubes=%s levels=%s integer=%s", list(cubes), levels, integer ) volume_cube = cubes.get("0") capacity_cube = cubes.get("1") if volume_cube is None or capacity_cube is None: return failure( "Expected two input nodes: volume per site, then capacity per country. " f"Received {len(cubes)}." ) try: volume = cube_to_frame(volume_cube, "volume") capacity = cube_to_frame(capacity_cube, "capacity") except (KeyError, TypeError, ValueError) as exc: logger.exception("could not parse input cubes") return failure(f"Could not read the input cubes: {exc}") # Levels are requested by name. Fail loudly here rather than silently # returning a cube of the wrong shape, which is much harder to debug from # inside a model. missing = [level for level in levels if level not in volume.columns] if missing: return failure( f"Input cube 0 has no column(s) {missing}. " f"It carries {sorted(volume.columns)}." ) # An empty input is normal, not an error: a modeller who closed every site # in a scenario sends nothing. Return an empty cube of the right shape so # the node calculates to zero instead of failing. if volume.empty: logger.info("no rows to optimize, returning an empty cube") empty = pd.DataFrame(columns=levels + ["optimized"]) return success( frame_to_cube(empty, levels, "optimized", volume_cube, "Optimized Volume"), "optimize", ) result = solve(volume, capacity, integer) # Sites the solver dropped must still appear, at zero. Leaving them out # makes them missing rather than closed, and downstream nodes then read the # previous value instead of nothing. if SITE_LEVEL in levels: result = ( volume[levels] .merge(result[levels + ["optimized"]], on=levels, how="left") .fillna({"optimized": 0.0}) ) output = frame_to_cube( result, levels, "optimized", volume_cube, "Optimized Volume" ) logger.info("/optimize returning %s rows", len(output["rowData"])) return success(output, "optimize") # --------------------------------------------------------------------------- app = FastAPI( title="Valsight API_CALL reference service", description=__doc__, version="1.0.0", ) app.include_router(PAGE, prefix="/functions") @app.get("/health") async def health() -> Dict[str, str]: return {"status": "ok"} if __name__ == "__main__": import uvicorn logging.basicConfig(level=logging.INFO, format="[%(levelname)s] %(name)s: %(message)s") uvicorn.run(app, host="0.0.0.0", port=8000) # --------------------------------------------------------------------------- # Try it without Valsight # --------------------------------------------------------------------------- # # curl -s localhost:8000/functions/optimize \ # -H 'Content-Type: application/json' -d '{ # "format": "JSON", # "version": "1", # "message": "continuous", # "maximum_mbs_to_return": "24", # "result_levels": ["Country", "Site"], # "inputs": { # "0": { # "version": "1", # "columnMetadata": [ # {"name": "Country", "columnType": "level", "levelId": 118}, # {"name": "Site", "columnType": "level", "levelId": 101}, # {"name": "measure", "columnType": "measure"} # ], # "tableMetadata": {"tableType": "FACT", "tableName": "Input 0"}, # "rowData": [["DE","S-100","1200"],["DE","S-101","900"],["JP","S-200","400"]] # }, # "1": { # "version": "1", # "columnMetadata": [ # {"name": "Country", "columnType": "level", "levelId": 118}, # {"name": "measure", "columnType": "measure"} # ], # "tableMetadata": {"tableType": "FACT", "tableName": "Input 1"}, # "rowData": [["DE","1500"],["JP","800"]] # } # } # }' | python3 -m json.tool # # DE is capped: 1200 + 900 = 2100 demanded against 1500 available, so both # sites scale by 1500/2100. JP stays at 400, well under its 800. ``` ## Related | Page | What it covers | | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | [API\_CALL](/api-call/) | The formula function itself: syntax, parameters, request and response reference, error messages. | | [DATA](/data/) | Referencing data that is already uploaded, instead of calling a live service. | | [Introduction to Valsight API](/introduction-to-valsight-api/) | Reading data out of Valsight, rather than being called by it. | --- # Building Models URL: https://docs.valsight.ai/building-models/ Description: This section explains what a model is in Valsight and how models serve as the foundation for structured business logic. It introduces how calculations, data,… This section explains what a model is in Valsight and how models serve as the foundation for structured business logic. It introduces how calculations, data, and assumptions are brought together to represent how a business works. Models created here are used across planning, forecasting, and simulation, forming the basis for analysis and downstream visualization. ## Who this section is for This section is relevant for users who want to understand how business logic is defined in Valsight and how models support different types of planning and analytical work across the platform. --- # Business Key URL: https://docs.valsight.ai/business-key/ Description: The Business Key is a unique identifier for each project. It is used when referencing a project in external contexts such as: The **Business Key** is a unique identifier for each project. It is used when referencing a project in external contexts such as: * [**Data Export Links**](/data-import-export/) * [**API Access**](/api-access/) This key ensures consistent identification across systems and integrations. ## Allowed format To ensure compatibility, Business Keys must meet the following requirements: * Minimum of **two characters** * Must **start with a letter** * Use **only uppercase letters, numbers, or underscores** * **No special characters or spaces** > ✅ Example: `SALES_2025` > ❌ Invalid: `sales-2025`, `2025_SALES`, `s_25` Business Keys are set during project creation and can be edited later by users with the appropriate permissions. --- # CAGR URL: https://docs.valsight.ai/cagr/ Description: The CAGR function computes the Compound Annual Growth Rate between a current value and the value N periods earlier, taking compounding into account. It works along a chosen level or any non-time dimension. **Category:** [Compare periods](/compare-periods/) ## Overview The **CAGR** function **computes the Compound Annual Growth Rate between a current value and the value N periods earlier**, taking compounding into account. It works along a chosen level (e.g. Year, Month) or any non-time dimension. Use this function when you need to measure compound growth over multiple periods, for example multi-year revenue growth. ## Syntax `CAGR('Node', NumberOfPeriods [, "Level" [, "InvalidHandling"]])` **Example usage:** `CAGR('Revenue', 3)` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------ | -------- | ----------------- | | **Node** | Input node whose values provide the end and start of the CAGR calculation | Node reference | Yes | -- | | **NumberOfPeriods** | How many steps back to compare. Must be a whole number >= 1. Can also be a node without dimensionality. | Number or node reference | Yes | -- | | **Level** | The level along which periods are counted | Level name | No | Time dimension | | **InvalidHandling** | Controls how rows with calculation errors (e.g. division by zero) are treated | Keyword | No | `"FailOnInvalid"` | **InvalidHandling options:** * `"FailOnInvalid"`: Any invalid entry causes an error. This is the default. * `"IgnoreInvalid"`: Invalid entries are silently omitted from the result. If all rows are invalid, the result is empty. ## Output shape | Aspect | Behavior | | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as input. | | Time range | The first N periods are dropped (no start value N periods back to compare against). Periods with missing start or end values are also dropped. | | Values | CAGR as a ratio: `(end_value / start_value)^(1/N) - 1`. A result of 0.5 means 50% compound annual growth. | | Row count | Reduced. At minimum, the first N periods are removed. | ## Watch out * If **Level** is omitted, the node must include a level from the **time dimension**. * The **Level** must be the **lowest level** in its dimension hierarchy on the input node. You cannot use a higher level (e.g. `"Year"` when the node has `"Month"` data). * The **Level** cannot be a **linked level** of another level on the node. * **NumberOfPeriods** must be a whole number >= 1. If it is a node, that node must have no levels. * A **start value of 0** causes a division-by-zero error. Use `"IgnoreInvalid"` to skip these entries instead of failing. ## Examples ### CAGR along the time dimension This example calculates the compound growth rate over 2 years for each country. Note that missing data points (e.g. US 2028) cause gaps in the result. **Input node:** `'Revenue'` | Year | Country | Value | | ---- | ------- | ----- | | 2025 | DE | 100 | | 2026 | DE | 200 | | 2027 | DE | 300 | | 2028 | DE | 400 | | 2029 | DE | 500 | | 2030 | DE | 600 | | 2025 | US | 100 | | 2026 | US | 200 | | 2027 | US | 250 | | 2029 | US | 300 | | 2030 | US | 400 | **Formula:** `CAGR('Revenue', 2)` **Equivalent to:** `CAGR('Revenue', 2, "Year")` **Equivalent to:** `CAGR('Revenue', 2, "Year", "FailOnInvalid")` | Year | Country | CAGR Result | | ---- | ------- | ----------- | | 2027 | DE | 73.21% | | 2028 | DE | 41.42% | | 2029 | DE | 29.10% | | 2030 | DE | 22.47% | | 2027 | US | 58.11% | | 2029 | US | 9.54% | There is no 2028 value for the US in the original data. This means the CAGR value cannot be calculated for 2028 (no end value) and 2030 (no start value 2 years prior). ### CAGR along a non-time dimension This example computes CAGR along the Product dimension instead of time, comparing each product to its predecessor in the dimension hierarchy. **Dimension: Product** | Level Name | Level Key | | ---------- | --------- | | Product A | 1 | | Product B | 2 | | Product C | 3 | **Input node:** `'Revenue'` | Year | Product | Value | | ---- | --------- | ----- | | 2025 | Product A | 100 | | 2025 | Product B | 250 | | 2025 | Product C | 200 | | 2026 | Product A | 150 | | 2026 | Product B | 250 | | 2026 | Product C | 250 | | 2027 | Product A | 200 | | 2027 | Product C | 300 | **Formula:** `CAGR('Revenue', 1, "Product")` | Year | Product | CAGR Result | | ---- | --------- | ----------- | | 2025 | Product B | 150% | | 2025 | Product C | -20% | | 2026 | Product B | 66.67% | | 2026 | Product C | 0.00% | Product A has no prior level in the dimension hierarchy, so no CAGR can be calculated. Product B and Product C both have prior levels. ## Related | Function | When to use instead | | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | [YOY\_REL](/yoy-rel/) | When you only need growth compared to one period back (no compounding). CAGR smooths growth over N periods; YOY\_REL gives the raw single-period change. | | [YOY\_ABS](/yoy-abs/) | When you need the absolute difference to the previous year, not a percentage growth rate. | | [DELTA\_REL](/delta-rel/) | When you need relative change along any dimension (not just time), without compounding. | --- # Calendar Months Dimension URL: https://docs.valsight.ai/calendar-months-dimension/ Description: Calendar months are an optional dimension that you can enable in the project settings. This will generate a “CalendarMonth” dimension with the levels 01, 02,… Calendar months are an optional dimension that you can enable in the project settings. This will generate a “CalendarMonth” dimension with the levels 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12. The calendar month dimension can be used to analyze seasonality effects in your business (e.g. profits per month and year for a skiing region). The difference between [calendar months](/calendar-months-dimension/) and the regular month Dimension is that calendar month does not contain the year, so you can compare the profits from a specific month over the years. ![calendarmonth-vs-month.png](./images/5094216289.png) ## Chart example using calendar months ![Untitled-1.png](./images/5094191333.png) ## Enable calendar months * In the **Project Settings View**, you can find a checkbox with the label - "System managed calendar months". ![Screenshot 2020-03-04 at 12.56.53.png](./images/5094191338.png) * Upon ticking the checkbox and clicking the Confirm button, a new dimension named “CalendarMonth” will be automatically generated. ![Screenshot 2020-03-04 at 12.58.47.png](./images/5094191348.png) * This dimension contains the calendar months and will be linked with the month level in the time dimension. ## Disable calendar months * When disabling the setting "System managed Calendar Months", the system will no longer automatically manage the dimension for you. However, it will not automatically delete the calendar month dimension (as this might lead to data loss). If required, the dimension can be deleted manually using the dimension management. * In order to re-enable calendar months, you have to delete the calendar month dimension using dimension management. --- # Changing the Time Horizon URL: https://docs.valsight.ai/changing-the-time-horizon/ Description: The time horizon of a project defines the amount of time you want to plan ahead - and want to have data in the past. The time horizon of a project defines the amount of time you want to plan ahead - and want to have data in the past. The time dimension is generated, according to the selection of the project time horizon, hence values out of the horizon are not part of the generation and may trigger errors when uploaded. To change it go to the project overview. Select the three dots button and select "Settings". Now you can change the default time horizon for your project. ![Screenshot 2019-12-12 at 10.40.01.png](./images/5094193695.png) Although not advised, and seldom needed, this setting can be overwritten in your workspaces ([Workspaces](/workspaces/) ). ## Overriding the horizon for a single model An individual model can also depart from the project horizon, which is what the glossary calls the *model horizon*. Set it in step 2 of the **Edit Model** dialog, reached from the model list: 1. Switch on **Override project simulation horizon**. 2. Choose the **Horizon Period**, then the **From** and **To** values. The three selectors stay disabled until the toggle is on, so a greyed-out Horizon Period means the model is still following the project horizon rather than that you lack the rights to change it. Two constraints are worth knowing: * The step is hidden entirely on a project using the **week** time dimension, so a model horizon cannot be set there at all. * Weeks are not offered as a model horizon period even where the step is shown. --- # Formatting Charts URL: https://docs.valsight.ai/chart-configuration/ Description: Sort, scale and format charts and tables so they read the way you want, from axis scales to table styles and overlapping labels. Once a chart shows the right data, formatting is what makes it readable: order, scales, colors, table styles, and what to do when labels collide. Select a chart and the chart editor opens on the right. The settings are spread over three sections of it, and a few live outside it altogether: | Section | What it holds | | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Axes** | Which levels sit on which axis, their order, and comparisons | | **Formatting** | Number and legend toggles, **Scales and Digits**, and the styling dialog for data series, columns and rows | | **Advanced Formatting** | **Stack Totals**, empty data series, [**Cross effects**](/assumption-effects/), **Freeze header columns**, **Bridge Settings** and other per-chart-type options | | Outside the chart editor | A node's own default scale, and the workspace setting for responsive text | ## Charts | If you | Go to | | ---------------------------------------------------------------- | ------------------------------------------------------------------------------- | | Put the level values in a custom order | [Sorting Level Values](/sorting-level-values/) | | Show a change as a delta or a percentage | [Delta Comparisons](/scenario-time-or-dimension-level-comparison-delta/) | | Set the scale, decimals or range of an axis, or add a second one | [Axis Scales and Decimals](/axis-scales-and-decimals/) | | Cut a large value range so small differences stay visible | [Y-Axis Breaks in Charts](/y-axis-breaks-in-charts/) | | Set the color, text style or value visibility of a data series | [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/) | | Stack data series and label their total | [Stacking and Stack Totals](/stacking-and-stack-totals/) | | Scale one node's numbers everywhere it is charted | [Default Scale Settings in Nodes](/default-scale-settings-in-nodes/) | | Let text scale with the size of the window | [Responsive Chart Text Size](/responsive-chart-text-sizes/) | | Get back values that disappeared where labels collide | [Overlapping Data Labels](/overlapping-data-labels/) | ## Tables | If you | Go to | | ------------------------------------------------------------ | ------------------------------------------------------------------------------- | | Switch the table style, resize columns or merge header cells | [Table Formatting](/table-formatting/) | | Mark subtotal and total rows, or indent them | [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/) | ## Related * [Data Display in Charts and Tables](/data-display-in-charts-and-tables/): which data a chart or table shows, and at which aggregation. * [Chart Types](/chart-types/): which chart or tile to use in the first place. * [Creating Charts](/creating-charts/): adding a chart, duplicating one, and saving a configuration as a template. --- # Chart Filter URL: https://docs.valsight.ai/chart-filter/ Description: Chart filters are the third level of filters available in a workspace. Chart filters are the third level of filters available in a workspace. Chart filters can be used to restrict the view in your chart so that they only display a subset of data. Every level used as one of the axes automatically gets a filter holding all of its values. Filter values are always chosen from a checkbox tree, so a filter can hold one value or many. What does differ is whether a filter is **dynamic** or fixed: * While **all** values of a level are selected, the filter is dynamic. It is not stored as a fixed list, so values added to that dimension later are included automatically. * The moment you deselect a single value, the filter freezes to the values you have ticked. New level values are then left out until you edit the filter. To limit the number of values on your axis, you can restrict the filter. You can always add a new filter by pressing the "Add Filter" button in the ‘Manage Filters’ dialog and selecting the dimension and level for the new filter. When you select the dimension and level for a new filter, the level picker includes a search box at the top. Start typing to narrow the list: it matches **dimension names first**, so matching a dimension keeps all of its levels, and otherwise matches **level names**. Matching is case-insensitive, and dimensions with no matching levels are hidden. ![image-20231002-114736.png](./images/6034751492.png) > Chart filters are limited by the applied workspace and worksheet filters. A workspace or worksheet filter only affects a chart whose data carries the filtered level; see [Workspace Filter](/workspace-filter/). --- # Chart Templates URL: https://docs.valsight.ai/chart-templates/ Description: Save a chart's configuration as a reusable template, then apply it when you add a new chart. Save a chart's configuration as a named template, then apply it the next time you add a chart instead of setting it up again. ## Goal Reuse a chart you have already configured, so that a layout you use often does not have to be rebuilt each time. ## Steps ### Save a chart as a template 1. Click the settings button at the top right of the chart to open its context menu. 2. Select **Save as template**. 3. Give the template a name that says what it is for. ### Apply a template to a new chart On a **new, empty sheet**, saved templates are offered on the selection screen straight away: ![Templates offered on the selection screen of an empty sheet](./images/5115019336.png) On a sheet that already has charts, start from the **Chart** button in the top bar: ![The Chart button highlighted in the top bar, beside the Scenario Manager button](./images/chart-button.png) Then pick **From Template**, in the **Template** group at the bottom of the selection, below **Others**: ![The chart type selection with the From Template option highlighted at the bottom](./images/5115281491.png) Choose the **Template** and the **Scenario** it should use, then click **Create**: ![The template and scenario drop-downs with the Create button](./images/5114921032.png) ## Verify The new chart appears with the saved configuration already applied: same chart type, axes and filters as the chart you saved it from. From there it behaves like any other chart, so changing it does not affect the template or the original. ## Related * [Creating Charts](/creating-charts/): adding a chart from scratch, and what you can set on it. * [Formatting Charts](/chart-configuration/): sorting, scales, colors and table styles. --- # Chart Types URL: https://docs.valsight.ai/chart-types/ Description: An overview of the chart types and worksheet tiles available in Valsight, in the same five groups you see when you add a chart. A chart in Valsight is a tile on a worksheet. Every type is added and configured the same way, so the only real decision is which one shows your data best. To add a chart, see [Creating Charts](/creating-charts/). To configure one you already have, see [Data Display in Charts and Tables](/data-display-in-charts-and-tables/). ## Start here if you want to: | If you | Go to | | ----------------------------------------------------------- | --------------------------- | | Compare figures, or show how they develop | [Diagrams](#diagrams) | | Read exact numbers across many dimensions | [Tables](#tables) | | Explain a difference between scenarios or between periods | [Bridges](#bridges) | | Let people simulate on the worksheet itself | [Simulations](#simulations) | | Show one KPI, the model behind it, or add text and pictures | [Others](#others) | | Rebuild a chart you have already configured once | [Template](#template) | ## Diagrams | Chart | Use it when | Example | | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | **Column Chart** | You want to compare key figures of the same dimensionality, for example profit across scenarios and years. Data series stand next to each other as vertical bars. | ![Column chart comparing revenue per region, with the regions side by side for each year](./images/column-chart.png) | | **Bar Chart** | You want the same comparison, but horizontally. | ![Bar chart showing the same revenue per region as horizontal bars grouped by year](./images/bar-chart.png) | | **Line Chart** | You want to see the trend of one or more key figures. Values are connected as lines, which makes the direction of the development easy to read. | ![Line chart comparing revenue across two scenarios from 2026 to 2033](./images/line-chart.png) | | **[Mixed Chart](/mixed-charts/)** | One data series has to stand apart from the others, for example a benchmark line drawn across a stacked breakdown. Each data series can be shown as a bar, line, area or spline. | ![Mixed chart with a red target line running across stacked simulation bars](./images/mixed-chart.png) | | **Area Chart** | You want a trend with the area under the line filled, so the volume behind the development is visible as well. | ![Area chart showing electric and non-electric car sales as two filled areas stacked to the market total](./images/area-chart.png) | | **Pie Chart** | You want the shares of a single total at one point in time. Proportions are shown as segments of a circle. | ![Pie chart showing CO2 emissions split across three scopes as segments of a ring](./images/pie-chart.png) | Stacking is a setting rather than a chart type: columns, bars, areas, lines and mixed charts can each be stacked. See [Stacking and Stack Totals](/stacking-and-stack-totals/). ## Tables | Chart | Use it when | Example | | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | **Table (all dimensions)** | You want the full detail in front of you: every dimension of the node, rather than an aggregate. This is the first entry under Tables. | ![Table showing revenue by region and engine type, with a subtotal per region and a grand total](./images/table-all-dimensions.png) | | **Table** | You want many figures at once, aggregated, with the dimensions you choose on rows and columns. Tables are how profit and loss statements, cash-flow statements and similar reports are built. | ![Table showing a profit and loss statement per year with a CAGR column on the right](./images/table.png) | A table only displays results. For one that readers can type into, see [Input Table](#simulations) under Simulations. For how to set the axes and choose the level of aggregation, see [Data Display in Charts and Tables](/data-display-in-charts-and-tables/). ## Bridges A bridge breaks a difference down into the individual effects that produced it. Both kinds use the same staircase shape, which the chart editor calls a **waterfall chart**, and they differ only in which difference they explain. | Chart | Use it when | Example | | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | **[Scenario Bridge](/scenario-bridges/)** | The steps should explain a difference between two or more scenarios, broken down by assumption, line-item or dimension. | ![Scenario bridge stepping from one scenario's gross profit to another through the effect of each assumption](./images/scenario-bridge.png) | | **[Time Bridge](/time-bridges/)** | Those effects should explain the change between two or more points in time within one scenario. | ![Time bridge stepping from the 2022 revenue to 2023 and 2024 through the effects in between](./images/time-bridge.png) | The steps do not have to be derived effects. Put **nodes** on the axis instead and you get a plain build-up, for example revenue and costs stepping down to gross profit. ## Simulations These tiles let people run simulations on the worksheet itself, rather than only read the results of one. | Tile | Use it when | Example | | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | **Scenario Manager** | You want the full Scenario Manager as a tile, so simulations can be run on the sheet itself. It is configured per sheet and looks the same for every user, unlike the stationary Scenario Manager. | ![A worksheet with the Scenario Manager as a tile in the top left, next to three charts](./images/scenario-manager.png) | | **[Input Table](/input-tables/)** | You want readers to enter values on the worksheet instead of only reading them. | ![Input table with editable sales growth percentages per region, engine type and year](./images/input-table.png) | | **[Slider](/sliders/)** | You want selected line-items adjustable directly on the worksheet, without opening the Scenario Manager. | ![A slider tile holding one slider per line-item, each with a percentage value box](./images/slider.png) | | **[Split Slider](/split-sliders/)** | You want to redistribute a total across its parts, for example a product mix or an allocation, while the total itself stays fixed. | ![A split slider with one track split into three shares of 28, 28 and 44 per cent](./images/split-slider.png) | ## Others | Tile | Use it when | Example | | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **[Tree](/model-tree/)** | You want to show the value driver structure behind the numbers. The nodes of the underlying model are drawn as a graph, the model tree, and can display values for several scenarios. | ![Model tree showing gross profit broken down into revenue and cost nodes, each node listing values per year](./images/model-tree.png) | | **Text** and **[Image](/images/)** | You want to add something to the worksheet that is not data: a headline, a list of targets, a note for other users, a logo or a diagram. These are the two tiles that turn a sheet of charts into something you can present from. | ![A worksheet headed by a text tile reading Integrated Business and Sustainability Strategy 2030, an image tile beside it, and a second text tile listing strategic targets above the charts](./images/text-and-image.png) | | **Packed Bubble Chart** | You want to compare the magnitude of many items at once, for example the effects of several assumptions. Size and color carry the meaning, the position of a bubble does not. | ![Packed bubble chart comparing sold quantities per engine type as three differently sized bubbles](./images/packed-bubble-chart.png) | | **[KPI](/kpi-charts/)** | One number is the point. A KPI chart shows a single figure with its unit and, optionally, a reference value such as the previous year. | ![KPI chart showing gross profit as one large number with the year below it and a CAGR reference at the bottom](./images/kpi-chart.png) | | **[Perspective Selector](/perspective-selector/)** | You want saved filter combinations, optionally with a picture each, that switch the view of the whole worksheet. It only appears if perspectives are enabled for your instance. | ![A worksheet with the perspective selector as a column of region cards down the left side, North America and Europe both selected](./images/perspective-selector.png) | ## Template Below the groups above sits one more option, **From Template**. It is not a chart type but a shortcut: it builds a new chart from a configuration you saved earlier, so a layout you use often does not have to be rebuilt. See [Chart Templates](/chart-templates/). ## Choosing between similar charts **Column Chart vs Bar Chart** * Use a **column chart** by default, especially when the x axis is time. * Use a **bar chart** when category names are long, or when there are many categories, because horizontal labels stay readable. **Stacking vs Mixed Chart** * Switch on **[Stacked](/stacking-and-stack-totals/)** when every data series should look the same and all of them belong to the total. * Use a **[mixed chart](/mixed-charts/)** when at least one data series has to look different, for example a target or a benchmark that should not disappear into the stack. **Scenario Bridge vs Time Bridge** * Use a **[scenario bridge](/scenario-bridges/)** to explain why one scenario differs from another, within one time period. * Use a **[time bridge](/time-bridges/)** to explain why one period differs from another, within one scenario. **Slider vs Split Slider** * Use a **[slider](/sliders/)** to change one line-item by an absolute amount. The total moves with it. * Use a **[split slider](/split-sliders/)** to shift shares between the parts of a total while the total stays fixed. **Table vs Table (all dimensions)** * Use **Table** for an aggregated view, then put the dimensions you actually want on the axes. * Use **Table (all dimensions)** to see every dimension of the node instead of an aggregate. **Table vs Input Table** * Use a **table** to display results. It is read-only, and sits under Tables when you add a chart. * Use an **[input table](/input-tables/)** when readers should type values into the worksheet. It sits under Simulations instead, because entering values runs a simulation. ## Related * [Creating Charts](/creating-charts/): how to add a chart, duplicate one, and reuse a configuration as a chart template. * [Data Display in Charts and Tables](/data-display-in-charts-and-tables/): sorting, colors, axes and the rest of the chart editor. * [Bridges](/bridges/): grouping assumption effects and adding intermediate sums in scenario and time bridges. --- # Clickable Submodel Label on External Nodes URL: https://docs.valsight.ai/clickable-submodel-label-on-external-nodes/ Description: Nodes that originate from another model (external nodes) show the source model's name in their bottom-right corner. This label is clickable and lets you navi… Nodes that originate from another model (external nodes) show the source model's name in their bottom-right corner. This label is clickable and lets you navigate directly to that model. ## How it works * Hover over the submodel label: it turns blue italic and a tooltip appears, "Go to submodel {name}" * Double-click the label: navigates to the source model and focuses the node * This is equivalent to the "Go to submodel" button in the Node Editor; both use the same navigation ![Double-click submodel.png](./images/6883016708.png) --- # Cloud SSO with Valsight ID URL: https://docs.valsight.ai/cloud-openid-connect/ Description: Connect your identity provider to a Valsight cloud instance through Valsight ID using OpenID Connect. > SSO configuration is a paid add-on for the Teams edition, and is included in the Corporate > and Enterprise editions. If you are unsure which edition your organization has, ask your > Valsight contact. ## Goal Your users sign in to your Valsight cloud instance with their existing company account, through your own identity provider. In the cloud, that connection is made through **Valsight ID** (`id.valsight.com`) — the central identity service that Valsight products trust. Your identity provider talks to Valsight ID, and Valsight ID vouches for the user to your instance. You register one application in your IdP and hand Valsight the connection details; Valsight sets up the connection. > **Looking for the on-premise SSO configuration?** This page is the cloud path. If you run Valsight on your own servers, the configuration lives on your instance instead — see [OpenID Connect](/openid-connect/) under On-Premise Installation. > **Prerequisites** > > * A Valsight account with administrator permissions > * Network access to your Valsight instance Verify access programmatically before proceeding: `GET {base_url}/api/v1/health` must return HTTP 200 with a valid API key in the `X-API-Key` header. ## Steps ### 1. Register an application in your identity provider Create a new application, app registration or client for Valsight, using the **authorization code flow**. Confidential clients are supported and preferred: Valsight ID keeps the client secret. ### 2. Add the redirect URL Your IdP will only send users back to an address you have allow-listed. There is exactly one for the cloud: ``` https://id.valsight.com/idps/callback ``` That is the same URL for every cloud customer and every Valsight cloud region — it belongs to Valsight ID, not to your instance. You do not need to register anything that contains your own instance hostname. ### 3. Make sure the required claims are present Two claims are mandatory for every OpenID Connect connection. Without them Valsight cannot identify the user, and sign-in fails: | Claim | Why it is needed | | ---------------- | --------------------------------------------------------------------- | | `email` | Identifies the user. Valsight uses the email address as the username. | | `email_verified` | Valsight only accepts an address your IdP states it has verified. | Optionally, you can also send group memberships. Valsight can use them to control who is allowed in and what they may see: | Claim | Purpose | | -------- | ------------------------------------------------------------------------------------------------------------------------------- | | `groups` | Group memberships, for restricting access or mapping to Valsight roles. Tell your Valsight contact which group names to expect. | For Microsoft Entra ID, the group claim is not sent by default. Add it under **App registration → Token configuration → Add groups claim**, and choose the group types you want Valsight to see. > Do not follow [Entra / AAD Configuration](/entra-aad-configuration/) for a cloud instance. That page documents the direct-to-instance setup, with callback URLs containing your own instance hostname. On the cloud path the only redirect URL is the Valsight ID one in step 2. ### 4. Send Valsight the connection details What Valsight needs depends on your provider. **Microsoft Entra ID** | Value | Where it is in Entra | | ----------------------- | ----------------------------------------- | | Application (client) ID | App registration → Overview | | Client secret | App registration → Certificates & secrets | | Directory (tenant) ID | App registration → Overview | **Any other OpenID Connect provider** | Value | Notes | | ----------------- | ------------------------------------------------------------- | | Client ID | From the application you created in step 1. | | Client secret | n/a for a public client; say so if your provider issues none. | | Issuer URL | The `iss` value your provider puts in its tokens. | | Authorization URL | Where users are sent to sign in. | | Token URL | Where the authorization code is exchanged. | | JWK URL | Where Valsight ID fetches your signing keys. | Many providers publish the last four at a discovery document under `/.well-known/openid-configuration`. If yours does, sending that one URL is enough. Send the secret through a channel you consider appropriate for a credential — ask your Valsight contact for a secure upload rather than putting it in an email body. ### 5. Tell Valsight which email domains to expect Users sign in with their email address, and Valsight ID works out which organization they belong to from the domain part of it. So every email domain your users sign in with has to be registered on your organization — for example `example.com` and `example.de` if both are in use. List the domains together with the details from step 4. ### 6. Optionally, name a logout URL By default, signing out of Valsight ends only the Valsight session. If you want users returned to your own logout page, provide that URL as well. ## Verify Valsight sets up the connection and then tests it with you. Two things are worth knowing about how that goes, because they are deliberate: * **The connection is inactive at first.** It exists, but it is not yet offered on the sign-in screen. That way a wrong issuer or a broken mapping cannot lock anyone out while it is being sorted out. * **Password sign-in stays available alongside it.** Your users can keep signing in as before while the new route is proven. Switching password sign-in off is a separate, later step, and it is only done once someone has actually signed in successfully through your provider. You are done when all of these hold: * The sign-in screen for your instance offers your organization's identity provider. * Signing in through it lands you in Valsight as yourself, with your email address shown in the user menu. * A colleague who is not in a permitted group is refused, if you asked for group-based restrictions. * Signing out behaves as you expect — Valsight session only, or a redirect to your logout URL. If sign-in fails, the message on the screen names the reason. Send it to your Valsight contact: the most common causes are a missing `email_verified` claim, an email domain that was not on the list in step 5, and a redirect URL that does not match step 2 exactly. ## SAML 2.0 OpenID Connect is the recommended protocol, and the rest of this page assumes it. SAML 2.0 is supported as well. The difference for you is that the two URLs your IdP needs contain a connection id, which Valsight can only give you once the connection has been created on the Valsight ID side. So the order is reversed: ask your Valsight contact for the connection first, then configure your IdP with what they send back. | Value | URL | | ------------------------- | ------------------------------------------------------------ | | ACS / reply URL | `https://id.valsight.com/idps//saml/acs` | | Service provider metadata | `https://id.valsight.com/idps//saml/metadata` | Everything else on this page applies unchanged: the same required attributes, the same email-domain registration, and the same inactive-first rollout. ## Related | Page | What it covers | | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- | | [Single-Sign-On (SSO) Configuration](/single-sign-on-sso-configuration/) | The overview of Valsight's SSO support. | | [Entra / AAD Configuration](/entra-aad-configuration/) | The direct-to-instance setup, where Entra talks to your instance rather than to Valsight ID. Not the cloud path. | | [OpenID Connect](/openid-connect/) | The on-premise path, where the configuration lives on your own instance. | | [Manage Users and Groups](/manage-users-and-groups/) | What happens to users and groups inside Valsight once they can sign in. | --- # Common SSO Options URL: https://docs.valsight.ai/common-sso-options/ Description: Edit the main configuration file conf/config.yml to fine tune behaviour of the application when using any SSO providers. Edit the main configuration file *conf/config.yml* to fine tune behaviour of the application when using any SSO providers. Two groups of keys live under `loginMethodConfigurations`. The first switches each authentication method on or off. | Configuration key | Description | Example | Default | | ------------------------- | -------------------------------------------------------------------------------- | ------- | ------- | | `formLogin → enabled` | Whether the application can be accessed via username and password authentication | `false` | `true` | | `apiKeyAuth → enabled` | Whether the application can be accessed via an API key authentication | `true` | `false` | | `saml → enabled` | Whether the application can be accessed via SAML authentication | `true` | `false` | | `openIdConnect → enabled` | Whether the application can be accessed via OpenID Connect authentication | `true` | `false` | The second group, under `commonSSOOptions`, applies to every SSO provider. | Configuration key | Description | Example | Default | | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- | ---------------------------- | | `autoCreateUsers` | Whether SSO access also creates the user in the application. Disabling it prevents the login of any user that is not already in the application. | `false` | `true` | | `autoCreatedUsersEnabled` | Whether users created by SSO access start enabled or disabled. Only has an effect when `autoCreateUsers` is `true`. See [Disabled auto-created users](#disabled-auto-created-users). | `false` | `true` | | `autoCreatedUserType` | The user type given to automatically created SSO users. See [User types for SSO users](#user-types-for-sso-users). | `analyst` | `unrestricted` | | `mandatoryGroupName` | A group that every user must belong to, as provided by the SSO. See [Mandatory group](#mandatory-group). | `groupName` | n/a | | `ssoLogoutUrl` | The URL the application redirects to after the user clicks the logout button. Preferably the SSO's own logout endpoint, so the user is logged out of both the application and the SSO system. | `https://samlserver.example.com/logout` | The application's login page | | `requiredGroupNamePrefixes` | Filters out groups in an SSO response that do not carry one of the listed prefixes. See [Required group name prefixes](#required-group-name-prefixes). | `AllowedPrefix1_` | n/a | ### Disabled auto-created users An administrator can manually enable such users in the application's user management. ### User types for SSO users There are four user types. Each accepts more than one spelling for `autoCreatedUserType`, and the value is case-insensitive: | User type | Accepted values | | --------------- | ---------------------------- | | Analyst / Basic | `analyst`, `basic`, `reader` | | Simulation | `simulator` | | Model | `modeler` | | Unrestricted | `unrestricted`, `admin` | The number of users per type is limited by the license. A user type does not grant any access rights or roles by itself — it only limits the access rights or roles a user can be given. See [Licenses, User Types and Access Management](/licenses-user-types-access-management/) for what each type can do. An unrecognized value does not stop the server: the user is created as the **Analyst / Basic** type and a warning is written to the log. If auto-created users come out with fewer rights than expected, check the value against the table above. ### Mandatory group Use this option when all users need to belong to the same group. It has no effect if synchronization is not enabled in the specific SSO configuration. If the SSO provider does not return the mandatory group for a user, that user cannot log in. ### Required group name prefixes If one or more prefix values are set, any group that matches none of them is treated as if it were not present in the SSO response. If no values are given, all groups are treated as valid. When `mandatoryGroupName` is also set, the mandatory group name must itself carry at least one of the prefix values. This option is available since 6.0.0 and is optional. --- # Compare periods URL: https://docs.valsight.ai/compare-periods/ Description: Use this category when you need to compare values across time, such as month-over-month or year-over-year changes. Use this category when you need to **compare values across time**, such as month-over-month or year-over-year changes. These functions help you shift values to a reference period and compute absolute or relative deltas. ## Start here if you want to: * Compare a metric to the **previous period**, such as month, quarter, year, or week * Use **standard growth metrics** such as `MOM`, `QOQ`, `YOY` * Choose between **absolute and relative changes**, for example a difference or a percentage change * Calculate **compound growth over multiple periods** with `CAGR` ## Not here if you want to: * Use cumulative totals or projections → see [Rollforward & time series](/rollforward-time-series/) * Reshape dimensionality first → see [Dimensionality & hierarchies](/dimensionality-hierarchies/) ## Mental model * **Shift**: move values along a time level to align the current period with a reference period * **Compare**: compute change vs a reference period as an absolute or relative difference * **Compound**: compute a compounded growth rate from a start value to an end value across multiple periods Most compare-period functions keep the same output shape as the input node. ## Common patterns | Name | What it does | Formula | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | | Compare to previous year | Use when you want to compute relative year-over-year change. | `YOY_REL('Sales')` | | Compute a generic delta | Use when you want the absolute change from one period to the previous one. Pass a dimension name to compare along a different dimension. | `DELTA_ABS('Sales')` | | Shift values | Use when you need explicit alignment before doing your own arithmetic. | `SHIFT('Sales', "Month", -1)` | | Use period shortcuts | Use when you want a direct previous-period series to combine with operators. | `PM('Sales')`, `PQ('Sales')`, `PY('Sales')`, `PW('Sales')` | | Compound growth over N periods | Use when you want a compounded annual growth rate over N periods. | `CAGR('Sales', 3)` | ## Functions in this category **Shift helpers** | Function | Description | | ---------------- | ------------------------------------------------------------------------------- | | [SHIFT](/shift/) | Shifts values along a specified level by a given offset (positive or negative). | | [PM](/pm/) | Returns the values for the previous month. | | [PQ](/pq/) | Returns the values for the previous quarter. | | [PY](/py/) | Returns the values for the previous year. | | [PW](/pw/) | Returns the values for the previous week. | **Generic delta functions** | Function | Description | | ------------------------- | -------------------------------------------------------------------------------------------- | | [DELTA\_ABS](/delta-abs/) | Calculates the absolute difference between consecutive values within the selected dimension. | | [DELTA\_REL](/delta-rel/) | Calculates the relative difference between consecutive values within the selected dimension. | **Standard period comparisons** | Function | Description | | --------------------- | ------------------------------------------------------------------------------ | | [MOM\_ABS](/mom-abs/) | Returns absolute month-over-month growth compared to the previous month. | | [MOM\_REL](/mom-rel/) | Returns relative month-over-month growth compared to the previous month. | | [QOQ\_ABS](/qoq-abs/) | Returns absolute quarter-over-quarter growth compared to the previous quarter. | | [QOQ\_REL](/qoq-rel/) | Returns relative quarter-over-quarter growth compared to the previous quarter. | | [WOW\_ABS](/wow-abs/) | Returns absolute week-over-week growth compared to the previous week. | | [WOW\_REL](/wow-rel/) | Returns relative week-over-week growth compared to the previous week. | | [YOY\_ABS](/yoy-abs/) | Returns absolute year-over-year growth compared to the previous year. | | [YOY\_REL](/yoy-rel/) | Returns relative year-over-year growth compared to the previous year. | **Compound growth** | Function | Description | | -------------- | ------------------------------------------------------------------------------ | | [CAGR](/cagr/) | Calculates the compound annual growth rate over a specified number of periods. | ## Choosing between similar functions **CAGR vs YOY\_REL (or other REL deltas)** * Use `YOY_REL` when you want a single-period relative change vs last year * Use `CAGR` when you want compounded growth across multiple periods **DELTA\_* vs MOM/QOQ/YOY/WOW*\* * Use `MOM`, `QOQ`, `YOY`, or `WOW` for common standard comparisons * Use `DELTA_ABS` or `DELTA_REL` when you want a delta without filling missing values **ABS vs REL** * Use `ABS` when you need a difference in the same unit as the measure, for example EUR * Use `REL` when you need a relative change, for example a growth rate **SHIFT vs PM/PQ/PY/PW** * Use `PM`, `PQ`, `PY`, or `PW` when previous month, quarter, year, or week is exactly what you want * Use `SHIFT` when you need a custom offset or a specific time level ## Pitfalls & troubleshooting * **Unexpectedly empty output**: check whether the reference period exists for those slices and whether missing values propagate through your calculation * **Misalignment**: confirm the time level you are operating on, for example month vs quarter vs year * `CAGR` **errors or gaps**: check whether the start and end values exist for the slice, whether `NumberOfPeriods` is a whole number greater than or equal to `1`, and whether you need a different invalid-handling behavior * **Behavior options**: if a function supports options such as `FirstValueBehavior` or `MissingValueBehavior`, verify which option is active and whether it matches your expectation ## Related * [Rollforward & time series](/rollforward-time-series/): running totals, moving windows, projections * [Operators](/operators/): combine current vs reference values using arithmetic and comparisons * [Formula basics](/formula-basics/): evaluation order, constants, and notation * [Troubleshooting guide](/troubleshooting-guide/): missing values, wrong shape, unexpected results --- # Comparisons & boolean operators URL: https://docs.valsight.ai/comparisons-boolean-operators/ Description: Comparisons and boolean operators turn values into conditions. Use them to test values, combine conditions, and drive branching logic, most commonly inside IF. Comparisons and boolean operators **turn values into conditions**. Use them to test values, combine conditions, and drive branching logic, most commonly inside `IF`. They return `1` for true and `0` for false. ## Start here if you want to: * Write a condition such as `'Revenue' > 1000` * Combine conditions with `AND`, `OR`, `NOT`, `XOR` * Use a `TRUE` / `FALSE` helper function * Write the condition part of `IF(condition, value_if_true, value_if_false)` ## Not here if you want to: * Search the catalog for a function page by name such as `GT`, `EQ`, `AND`, or `IS_NA` → see [Logical functions](/logical-functions/) * Find branching behavior and examples for `IF` specifically → see [IF](/if/) ## Mental model * Comparisons between two nodes run over the union of both inputs' intersections, not only the rows they share, and return 1 (true) or 0 (false) * Boolean operators combine or invert conditions and also return 1 or 0 * `TRUE('Node')`/ `FALSE('Node')` returns 1/0 wherever `'Node'` is defined * `IS_NA('Node')` returns 1 where `'Node'` is undefined (and can expand result size) * In `IF`, 0 is interpreted as false and any other value as true ## Comparison operators | Operator | Function equivalent | Details | Returns 1 when… | | -------- | ----------------------- | ----------------- | -------------------------------------- | | `=` | `EQ('Node1', 'Node2')` | [EQ (=)](/eq/) | values are equal | | `!=` | `NEQ('Node1', 'Node2')` | [NEQ (!=)](/neq/) | values are not equal | | `>` | `GT('Node1', 'Node2')` | [GT (>)](/gt/) | left is greater than right | | `>=` | `GTE('Node1', 'Node2')` | [GTE (>=)](/gte/) | left is greater than or equal to right | | `<` | `LT('Node1', 'Node2')` | [LT (<)](/lt/) | left is less than right | | `<=` | `LTE('Node1', 'Node2')` | [LTE (<=)](/lte/) | left is less than or equal to right | Many comparisons can be written either as a function call or as an operator expression, for example `GT('Node1', 'Node2')` or `'Node1' > 'Node2'`. Comparisons cannot be chained: at most one `=`/`!=` and one `<`/`<=`/`>`/`>=` may appear per expression level, so `0 < 'Revenue' < 100` and `'A' = 'B' = 'C'` are syntax errors. Write `(0 < 'Revenue') && ('Revenue' < 100)` instead. ## Boolean operators | Operator | Function | Details | Returns 1 when… | | -------- | ----------------------- | ----------------- | -------------------------- | | `&&` | `AND('Node1', 'Node2')` | [AND (&&)](/and/) | both inputs are true | | `\|\|` | `OR('Node1', 'Node2')` | [OR (\|\|)](/or/) | at least one input is true | | none | `NOT('Node')` | [NOT](/not/) | input is false (0) | | none | `XOR('Node1', 'Node2')` | [XOR](/xor/) | exactly one input is true | `&&` and `\|\|` are the only boolean infix operators. `AND`, `OR`, `NOT` and `XOR` exist as functions only, so they always need parentheses and comma-separated arguments. These are most commonly used inside `IF` conditions. ## Defined/undefined helper functions | Function | Details | Returns | | --------------- | ----------------- | ---------------------------- | | `TRUE('Node')` | [TRUE](/true/) | 1 on defined intersections | | `FALSE('Node')` | [FALSE](/false/) | 0 on defined intersections | | `IS_NA('Node')` | [IS\_NA](/is-na/) | 1 on undefined intersections | ## Common patterns | Name | What it does | Formula | | ------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------ | | Flag positive values | Returns 1 where the value is above zero, else 0. | `'Value' > 0` | | Combine conditions | True when either condition holds. | `('Margin' < 0) \|\| ('Revenue' = 0)` | | Branching logic | Returns one value where the condition holds, another where it does not. | `IF('Net Income' > 0, 'Net Income' * 'PayoutRate', 0)` | | Truthiness shortcut | Treats any non-zero value as true. | `IF('Delta', 1, 0)` | | Check whether a node is defined | Uses `TRUE` as the condition to select defined cells. | `IF(TRUE('Sales'), 'Node1', 'Node2')` | | Find missing intersections | Returns 1 where the node is undefined. | `IS_NA('Sales')` | ## Pitfalls & troubleshooting * **Truthiness surprises**: in conditions, `0` is false and any non-zero value is true * **Defined vs undefined**: `TRUE('Node')` and `FALSE('Node')` apply where the node is defined; use `IS_NA('Node')` to detect undefined intersections * **Cube size risk**: `IS_NA` can expand result size significantly * **Missing is compared as zero, not skipped**: when two nodes are compared, a side with no row at an intersection is treated as `0` and the comparison still returns a defined 1 or 0. `'A' > 'B'` therefore returns 1 wherever `'A'` is positive and `'B'` has no row, and a comparison never returns N/A. Use `IS_NA` to tell a real zero from a missing value. The same coercion applies to `&&`, `\|\|` and `XOR` * **A plain number behaves differently**: comparing a node against a constant, as in `'Revenue' > 0`, broadcasts the constant over the rows the node already has. No rows are added, so intersections where the node is undefined stay undefined * **Dimensional mismatch**: some logical functions, such as `XOR`, may behave unexpectedly when inputs differ in granularity ## Related * [IF](/if/): how conditions are interpreted in `IF` * [Formula basics](/formula-basics/): parentheses, evaluation order, and quoting rules * [Troubleshooting guide](/troubleshooting-guide/): wrong shape, wrong numbers, empty output, and missing values --- # Compliance & Security URL: https://docs.valsight.ai/compliance-security/ Description: Compliance & Security How Valsight handles compliance and security: data protection and GDPR, the TISAX and ISO commitments, signed releases, audit logging, hosting options, and how to reach the security team. --- # Complying with GDPR Requirements URL: https://docs.valsight.ai/complying-with-gdpr-requirements/ Description: GDPR requirements typically require organisations to securely log and store data in an audit-proof manner. Valsight offers extensive features and tools to ea… GDPR requirements typically require organisations to securely log and store data in an audit-proof manner. Valsight offers extensive features and tools to easily comply with these requirements. Below you can see the options for exporting and storing data, from user to model and assumption data. > The exports listed below are usually provided as a comprehensive, audit-proof document containing all the necessary information. Unlike the usual export formats, these exports are not intended for manipulation and uploading of project data. Please refer to our [Export Manager](/export-manager/) documentation to see how to download usable data that can be uploaded and shared between projects. ## 1. Personal data ### a. User Report - logging & downloading user data > Access: global admin Valsight logs all user actions by default. This allows an administrator to download user data to comply with any GDPR requirements. The data includes the users personal data as well as any in-app activity such as exports created, scenarios deleted or data updated. To download a user's personal data, navigate to the ‘Users' tab in the 'Settings’. ![Screenshot 2024-08-26 100522.png](./images/5678956568.png) Select a user by clicking on their name and navigate to the 'User Report' button at the bottom. ![Screenshot 2024-08-26 100740.png](./images/5679054870.png) Clicking this button will download this user report data in csv format. User data includes all personal information and in-app activity: ![Screenshot 2024-08-26 100714.png](./images/5679579164.png)![image-20240826-094300.png](./images/5679841295.png) ### b. Auto-Delete of user data > Access: global admin Valsight stores user data and activities indefinitely by default. This can be changed for each user by an admin through the user's settings. Automatic deletion of a user's personal data is tied to the 'Exclude from automatic deletion' setting, which prevents a user's data from being deleted. To change this for a user, navigate to a user's settings via 'Settings' → 'Users' → click on the required user and click on the 'Edit User' button at the bottom of the page. ![Screenshot 2024-08-26 100735.png](./images/5679480838.png) Navigate to the 'Exclude from automatic deletion' setting and deselect it to allow automatic deletion of this user's personal data. Deselecting it means that the personal data will be deleted after a configured time\*. ![Screenshot 2024-08-26 100811.png](./images/5679022133.png) \*The global auto-delete time can be configured via the instances' config.yaml file. This can only be configured before startup and requires a restart of the application. Contact support for more information. ## 2. Project data ### a. Downloading scenarios with variables & assumptions > Access: any user with access to the workspace and scenario To download scenario information, including all variables and assumptions, navigate to the Scenario Manager of a workspace. Navigate to the scenario you wish to download and click on the three-dot menu. ![Screenshot 2024-08-26 100940.png](./images/5679120415.png) Clicking on 'Download active Assumptions' will download the scenario in xlsx format. ![Screenshot 2024-08-26 100953.png](./images/5679284232.png) Unlike the normal scenario export, this file also includes sheets with all active assumptions and variables for full transparency. ![Screenshot 2024-08-26 101017.png](./images/5679415340.png)![image-20240826-100256.png](./images/5679939619.png) ### b. Downloading all models, data sources & dimensions > Access: unrestricted users with access to the desired project / global admin It is possible to download all of a project's models, data sources or dimensions at once in an audit-proof format. To do this, navigate to the Projects tab on the Settings page. ![Screenshot 2024-08-26 101049.png](./images/5679710232.png) Select a project by clicking on its name. On this page the three download buttons 'Download Models', 'Download Datasources' & 'Download Dimensions' will each create a download. The number at the beginning of each line is the number of items for that item. The download consists of a zip file with all items in .txt format. ![Group 43.png](./images/5679185950.png) --- # Configuration of Websockets URL: https://docs.valsight.ai/configuration-of-websockets/ Description: The Valsight frontend uses Websockets to communicate with the Valsight backend in an interactive, bi-directional way. The Valsight frontend uses Websockets to communicate with the Valsight backend in an interactive, bi-directional way. Websockets are a bi-directional protocol, designed to be usable through typical web components like load balancers and proxy servers. To initiate a websocket connections, the client sends an HTTP Upgrade request. More details can be found on [Wikepedia - WebSocket](https://en.wikipedia.org/wiki/WebSocket). By default, most load balancers and proxy servers do not forward websocket requests to the backend, and thus this support must be enabled. ## Enabling websockets Refer to your reverse proxies or load balancers manual for enabling websockets. See [On-Premise Installation Guide](/on-premise-installation-guide/) for an Apache2 example. ## Fallback mechanism If the Valsight frontend cannot establish a websocket connection it defaults to a HTTP Polling mechanism. In theory this should enable the user to use all features of the app in the same fashion. However, it leads to an increased HTTP workload, as many HTTP requests (thousands per minute) can originate from a single client. Please ensure that your infrastructure does not rate limit such requests. We are using and its included fallback mechanism. --- # Compare a Total with a Breakdown URL: https://docs.valsight.ai/configure-flexible-scenario-comparisons-in-a-single-chart/ Description: This guide shows you how to compare multiple scenarios in a single chart while displaying totals for one scenario and detailed breakdowns for another. ## Goal This guide shows you how to compare multiple scenarios in a single chart while displaying totals for one scenario and detailed breakdowns for another. You will create a [mixed chart](/mixed-charts/) where: * **Scenario 1** (for example, *Basic*) is shown as a total line. * **Scenario 2** (for example, *Discussion (Realistic Case)*) is shown as a stacked breakdown. * Hidden elements remain part of the configuration but are not displayed in the chart or legend. ## Prerequisites * You have access to a Workspace. * The node you want to analyze exists (for example, **Gross Profit**). * At least two scenarios are available. ## Steps ### Create a mixed chart on your target node 1. Open your **Workspace**. 2. Add a new **mixed chart**. 3. Select the node you want to analyze (for example, *Gross Profit*). 4. Keep the default axes: * **X-axis:** Time * **Data series:** Scenario At this stage, scenarios are displayed across time. ### Filter to two scenarios 1. Open the **Filters** section. 2. Filter the **Scenario** dimension. 3. Select the two scenarios you want to compare (for example, *Basic* and *Discussion (Realistic Case)*). 4. Save the filters. ### Configure axes 1. Open **Configure Axes**. 2. Set: * **X-axis:** Time * **Data Series:** * Scenario * Engine (total) * Engine 3. Activate the **Subtotals for x-axis** toggle. 4. Confirm the configuration. ![The Configure Axes dialog with Time on the x-axis and Scenario, Engine (total) and Engine as data series](./images/6703808516.png) This setup enables both totals and detailed breakdown levels to coexist. ### Configure data series visibility and chart types 1. Open **Data Series styling**. 2. In the list of series, locate the entries for both scenarios. #### For scenario 1 (e.g. “Basic”) 3. Keep only the **Total** visible. 4. Hide the detailed breakdown levels (e.g. ICE, BEV, PHEV). 5. Set the **Total** to display as a **Line**. #### For scenario 2 (e.g. “Discussion (Realistic Case)”) 6. Hide the **Total**. 7. Keep the detailed breakdown levels visible. 8. Confirm your changes. ![The data series styling dialog, with one scenario's total set to Line and its breakdown levels hidden](./images/6703185932.png) ### Ensure bars are stacked 1. In the chart settings, activate **Stacked**. 2. Save the chart. ## Verify ![The finished chart, with one scenario as a total line running across the other scenario's stacked bars](./images/6703087621.png) Your chart now displays: * **Scenario 1** (e.g. *Basic*) as a single total line across time. * **Scenario 2** (e.g. *Discussion (Realistic Case)*) as stacked bars showing internal composition. This allows you to compare: * Overall performance differences between scenarios. * Structural drivers within one scenario. * Total vs. composition in a single, consolidated view. The result is a flexible comparison layout similar to the illustrated example, where one scenario provides a benchmark line and the other reveals detailed category contributions in stacked form. ## Pitfalls & troubleshooting **The totals are not appearing correctly.** Ensure that: * Subtotals for the x-axis are activated. * The “Total” level is included in the data series. **The filter behaves unexpectedly.** Select the scenarios first, then configure axes with the “All” level. --- # Configure the Sequence Dimension URL: https://docs.valsight.ai/configure-the-sequence-dimension/ Description: The Sequence dimension is a special system dimension used to describe abstract steps or "periods after time." It's commonly used in models where events unfol… The **Sequence dimension** is a special system dimension used to describe abstract steps or "periods after time." It's commonly used in models where events unfold relative to a time value, such as **depreciation models**, **efficiency curves**, or **growth timelines**. Rather than using calendar-based time (like years or months), the Sequence dimension allows you to model concepts like “Year 0”, “Year 1”, … “Year 9”, representing steps from a starting point. ## Default behavior By default, the system generates a Sequence dimension with values ranging from **0 to 9**, which fits most use cases on a yearly level. However, for more complex models, especially those working on a **monthly basis** or requiring longer timelines, this range may not be sufficient. In those cases, the maximum number of sequence values must be extended. ## How to extend the sequence dimension **FOR ADMINS-ONLY** To extend the number of generated Sequence dimension values, follow the steps below. 1. Click the **⚙️ cog icon** in the left-hand side navigation bar to open the Admin UI 2. In the Admin UI, go to **Projects** 3. Select the desired project from the list on the left 4. Below the project’s information on the right, click the **Settings button** 5. Scroll to or search for the **Dimensions** section 6. Locate the field: `featureFlags.sequenceDimensionAutoGeneratedMax` 7. Enter the new maximum number of steps (e.g., 120 for 10 years of monthly steps) ## When the change takes effect The change to the Sequence dimension **only takes effect after a re-upload** of the data source that contains the `SEQ_DIM`table. This is usually the **first data source** in your project. After upload, the sequence values will regenerate according to the new maximum. ## Important considerations * **Changing the max value affects how sequence level values are formatted.** The Sequence dimension uses **fixed-width level values**, and the number of leading spaces depends on the maximum. For example: * Max = 99 → first value = `"0"` * Max = 999 → first value = `"0"` * **Entering sequence values manually in Excel:** Use single quotes to preserve leading spaces (e.g. `‘0`) * **Existing models may need adjustments:** If models use the `TIMELAG()` function or reference specific sequence values, these **may need to be updated** to reflect the new value format. --- # Configure Units URL: https://docs.valsight.ai/configure-units/ Description: Project administrators with a modeling license can create, edit, and delete units within a project. Units are scoped to the project level: each project contains only the units defined for it. Project administrators with a modeling license can create, edit, and delete units within a project. Units are scoped to the project level: each project contains only the units defined for it. ## Prerequisites Project administrator role with a modeling license. ## How to get there **Option A (recommended)** In the project overview, open the **...** menu next to the project > **Project Settings > Configure Units > Units**. **Option B** Open **Valsight Settings** (cog icon in the left navigation) > **Projects** > select the project > **Show Units > Units**. ![Project\_Show Units.png](./images/6877249598.png) ## Default units Every new project automatically includes a set of default units. ![Units list.png](./images/6876954681.png) ## Creating a unit 1. On the Units page, click **Add unit**. 2. Fill in the configuration fields: | Field | Description | | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | Name | The name of the unit as shown in the inspector and dropdowns. | | Short sign | The symbol shown in tables and charts. | | Unit Placement | Position of the symbol relative to the value (`$10` vs `10€`). Select **None** to omit the symbol (e.g. for FTEs). | | Scale | Default display scale (e.g. `k` = Thousand, `m` = Million). Can be overridden at the node, chart, or table level. | | Decimal Places | Default number of decimal places. Can be overridden at the node, chart, or table level. | | Unit Type | Used for validation. Valsight flags invalid combinations across unit types (e.g. adding units of different types). Use **scalar** if unsure. | 3. Save the unit. ## Editing a unit Select the unit from the list, update the desired fields, and save. ## Deleting a unit A unit can only be deleted when it is no longer assigned to any node. If it is still in use, the delete option will not be available. Once unassigned, select the unit and click **Delete**. ## Copying units across projects When copying nodes between projects, Valsight matches units by **name**. If a matching unit exists in the target project it is reused; otherwise it is created automatically. No manual action is required. ## Related * [Units](/units/) --- # Connect Claude to the Valsight MCP server URL: https://docs.valsight.ai/connect-claude-to-valsight-mcp/ Description: Connect Claude — on claude.ai or in Claude Code — to the Valsight MCP server so it can work with live data from your Valsight projects. ## Goal You will have Claude connected to the [Valsight MCP server](/valsight-mcp-server/), so it can read — and, in a write session, change — data in your Valsight projects on your behalf. Setup takes about five minutes and works both on **claude.ai** and in **Claude Code** (the terminal). Both use the same server, the same sign-in, and the same permissions. > **Prerequisites** > > * A Valsight account with administrator permissions > * Network access to your Valsight instance Verify access programmatically before proceeding: `GET {base_url}/api/v1/health` must return HTTP 200 with a valid API key in the `X-API-Key` header. The MCP server must also be **enabled for your Valsight instance** — it is a premium feature, opted into per customer (see [availability and pricing](/valsight-mcp-server/)). The server is remote, so there is nothing to install; Claude connects to it over the internet. ## Your MCP server address The address is your instance's URL carried as a query parameter on the shared MCP server host: ``` https://mcp.valsight.ai/mcp?monolithUrl=https://.valsight.com ``` It is one continuous address with no spaces — select and copy it in one piece. Replace `.valsight.com` with your own Valsight instance URL; if you are unsure of it, ask your Valsight admin. ## Steps ### Connect on claude.ai 1. Open the connector settings: your initials (bottom left) → **Settings** → **Connectors**. 2. Click **Add custom connector** and name it `Valsight`. 3. Paste your [MCP server address](#your-mcp-server-address). Leave **Advanced settings** (Client ID / Secret) empty — registration is automatic. 4. Click **Add**, then **Connect**. The login window opens (see [The sign-in flow](#the-sign-in-flow)). 5. Once the connector shows **Connected**, enable Valsight from the tools menu (the sliders icon) in any new chat. ### Connect with Claude Code For working in the terminal — same server, same login, same permissions. 1. Sign in to Claude Code (first time only): open a terminal, run `claude`, and sign in with your Anthropic account. 2. Register the MCP server in one command: ```bash claude mcp add --transport http valsight \ "https://mcp.valsight.ai/mcp?monolithUrl=https://.valsight.com" ``` 3. Authenticate: run `/mcp` → **valsight** → **Authenticate**. The same OAuth flow opens in the browser. 4. Tip: add `--scope user` to the `add` command to make the server available in all your projects. ### The sign-in flow Sign-in is one-time. Afterwards the connection stays active and tokens refresh automatically. 1. The browser opens **id.valsight.com** — Valsight's own identity service. This window is expected. 2. Approve the authorization request ("MCP Client requests access"). This authorizes Claude to act with your permissions. 3. Log in with your **existing** Valsight account — your work e-mail and Valsight password. Never click **Register**; your account already exists. ## Verify * **On claude.ai:** the connector shows a green **Connected**, and Valsight appears in the tools menu of a new chat. * **In Claude Code:** `claude mcp list` shows `valsight` as connected. * **End to end:** ask Claude something that needs live project data (for example, to list your projects). A grounded answer confirms the bridge works. ## Control the session By default an MCP session can **write** — it can change your models. Scope it deliberately. Use the session-management page to set the active session to **read-only** or restrict it to specific projects: ``` https://mcp.valsight.ai/management/ ``` Session scope, access level, and data access, and their defaults, are covered in [Session scope and permissions](/valsight-mcp-server/#session-scope-and-permissions). Your Valsight sign-in stays valid for 12 hours, after which you sign in again. ## Help Login trouble, or projects missing after you connect? Contact your Valsight admin. ## Related * [Valsight MCP integration](/valsight-mcp-server/): what the server is, its capabilities, and how session scope keeps a connection contained. * [FAQ: Valsight MCP integration](/frequently-asked-questions-valsight-mcp-integration/): connecting, security, and prerequisites. * [Valsight AI](/ai-assistant/): overview of both ways to use Valsight AI. --- # Create and Update Data Sources - Step by Step URL: https://docs.valsight.ai/create-and-update-data-sources-step-by-step/ Description: On this page we will be listing the steps to upload base data and check it's validity. Please note that your Excel file needs to follow the structural guidel… On this page we will be listing the steps to upload base data and check it's validity. Please note that your Excel file needs to follow the [structural guidelines for Valsight data](/limitations-data-sizing-guidelines/). ## Step 1: creating data sources Open or create a new model and select 'Upload Data' on the top right of the screen. This will open the data upload wizard. Now select 'Create new datasource' at the bottom to create a new data source. > If you want to modify an existing data source you can click the 'Upload' button on the right and skip to step 2. ![eng Data upload wizard v2.17.png](./images/5094190537.png) Valsight will redirect you to a new page, on which you can select 'New Data Source' → 'XLSX'. ![New Datasource backend.png](./images/5094216512.png) On the following page, you can name the data source (please note the [Naming Guidelines](/naming-guidelines/)) and select an Excel file to upload. The file will only be a placeholder since we will upload a new one later. Once this is finished you can click 'Create Data Source'. ![new datasource name and file backend v2.15.png](./images/5094216452.png) Now go back to your model and select 'Upload Data' once again. ## Step 2: upload data On the model page, select “Upload Data” to open the upload wizard. ![Data Upload in Model Editor.png](./images/5094230309.png) Since we are back in the data upload wizard, you can select 'Upload' next to the previously created data source. Now 'Browse' and select the excel file containing the desired data. Hit 'Check Content' once it's selected. ![eng Upload browse for file v2.17.png](./images/5094190532.png) ## Step 3: validate data At this point, the software will display an overview showing which columns and tables were recognized. If everything is ok, you can hit 'Validate Content'. ![eng data upload validate content v2.17.png](./images/5094190607.png) Now the data is getting validated. If everything worked correctly, the data upload wizard will display ‘No problems were found’. In this case, you can 'Upload' your new data source. ![eng validation result positive v2.17.png](./images/5094190602.png) #### Possible problems Check if your [Dimension & Hierarchy Management](/creating-maintaining-dimensions/) is configured correctly if the software shows unknown columns. ![data upload validate content error v2.15.png](./images/5094216698.png) If there is an error during the validation process, please check [Data Upload Errors, Warnings, and Infos Explained](/data-upload-errors-warnings-and-infos-explained/). Alternatively, you can click on the error message to be redirected to the corresponding entry on our documentation. ![validation result error v2.15.png](./images/5094216707.png) --- # Create one Excel Sheet for Multiple Data Nodes URL: https://docs.valsight.ai/create-one-excel-sheet-for-multiple-data-nodes/ Description: This method is only compatible when using data Nodes in your Model. Starting with Version 1.19 (January 2018) we recommend to use only calculation Nodes with… Usually, the underlying concept for creating data tables is that the data of Worksheet is used for one Node in the Model – implying that one Node only references one excel sheet. *Important: This method is only compatible when using data Nodes in your Model. Starting with Version 1.19 (January 2018) we recommend to use only calculation Nodes with the [DATA](/data/) function.* This is the case for most data tables. However, there is one way to create datatables in one Worksheet that contain the information for multiple Nodes. The layout of this data table is similar to the 2D Tables, however Column A now doesn‘t reference a Dimension anymore. Instead of defining a Dimension, type $Node into cell A1. Then, fill the column with the names of the Nodes that you want to create a data entry for. This approach will make your excel sheet more organized, as you don‘t have to create as many Worksheets. However, that would of course work, too. --- # Create Upload Tables URL: https://docs.valsight.ai/create-upload-tables/ Description: There are important Naming Guidelines to follow when choosing worksheet and column names. The default way to upload your data into Valsight are regular tables. These tables are organized like a classic relational table. *Important: Follow the [Naming Guidelines](/naming-guidelines/) when choosing worksheet and column names.* These tables can contain zero or more levels, they are the most flexible way to upload data. Some examples: A table with no dimensional information, not even time: | Measure | | ------- | | 10 | A table that contains one numeric value per year: | Year | Inflation | | ---- | --------- | | 2018 | 2% | | 2019 | 3% | A table that contains multiple numeric values per year: | Year | Inflation | InterestRate | | ---- | --------- | ------------ | | 2018 | 2% | 4% | | 2019 | 3% | 5% | A table that contains two levels and multiple values | Year | Country | Inflation | InterestRate | | ---- | ------- | --------- | ------------ | | 2018 | DE | 2% | 4% | | 2019 | DE | 3% | 5% | | 2018 | US | 4% | 2% | | 2019 | US | 2% | 3% | See an Example at [Example Excel Sheets](/example-excel-sheets/). --- # Creating a Line-Item URL: https://docs.valsight.ai/creating-a-line-item/ Description: 1. To add a Line-Item to your assumption, click on the “+” button on an assumption. Add a line-item to an assumption, choosing which simulation nodes it applies to and whether each one is absolute or relative. 1. To add a Line-Item to your assumption, click on the “+” button on an assumption. 2. In the first step to create a Line-Item, you can select one or multiple simulation nodes for which you wish to create line items. 3. All line items are “Absolute” by default. In the next step you can mark some or all as “Relative” as well as assign a name for each line item. 4. Click ‘create’ to create the defined line items. ![image-20240523-123725.png](./images/5533466633.png) ## Absolute Line-Item * Used to enter absolute values as the change to your base data * Has a fixed dimensionality which cannot be changed ## Relative Line-Item * Used to enter relative values as the change to your base data * The dimensionality of a relative Line-Item can be adjusted * In a relative Line-Item it is possible to select a hierarchically higher level in the dimensionality, which will aggregate the lower level values into the new level E.g. The Line-Item is based on ‘Months’ in the ‘Time’ dimension. By changing the dimensionality and selecting ‘Year’ from the ‘Time’ dimension, all the values from ‘01-2023’ till ‘12-2023’ will be aggregated to ‘2023’. Whether a line-item is absolute or relative is a property of the line-item, not of the node. A percentage unit on the node does not make changes to it relative, and it is not a prerequisite for creating a relative line-item. > **A relative line-item needs something to scale** > > A relative line-item multiplies the node's calculated value. If that value is 0, the result stays 0 and the line-item appears to do nothing. This is the normal case on a model kept deliberately neutral, where the node computes something like `EXPAND(0, ...)` and all the movement is meant to come from the Scenario Manager. > > Adding an absolute line-item to the same node does not help. Relative line-items are applied to the node's own value first and absolute ones are added afterwards, so the relative one never sees the absolute change. Either use an absolute line-item, or give the node a base value for the relative one to scale. --- # Creating a Model Copy URL: https://docs.valsight.ai/creating-a-model-copy/ Description: Learn how to create a copy of a Model and how to use that copy. Create a copy of a Model and use that copy. Duplicating a model is useful for experimentation, or for incremental changes to a model you still want to keep in its original state. Duplicating models with submodels requires a few extra steps. ## Steps ### Open the model's three-dot menu On the modeling overview page, open the three-dot menu of the model you want to copy. ### Select the Duplicate option Choose **Duplicate** from the menu. ### Adjust the name and description In case it is needed, the name and the description can be changed. ![Duplicating Model.gif](./images/5094215553.gif) ## What you have done The copy is accessible on the modeling overview page. Subsequent copies of the same model are named ("Model Name" Copy X), with X being the ascending number of the copy, starting from 1. ## Duplicating a model with submodels When duplicating a model with submodels, all links to the submodels stay intact, but references to the model are not changed and keep pointing to the original. To create a copy of a complex model with submodels follow these steps: 1. Copy the lowest level of models, e.g. all models without submodels. Give them a unique name, e.g. prefix them with V2 or similar. 2. Copy the next level of models and add all model copies of the previous step as submodels. Don't remove the original/old submodels just yet. Change all connections to nodes of submodels to the submodel copies. Now remove the original/old submodels. 3. Repeat step 2 for each parent model. ## How to create a model copy including the workspaces If you want to copy not only a model but also a corresponding workspace, there are a few extra steps to take. 1. Duplicate the model as explained above. If the model has submodels, take the additional steps to migrate them as well. 2. Go to the admin UI and navigate to the original model 3. Open the workspace(s) and migrate them to the copy of your model --- # Creating a Project URL: https://docs.valsight.ai/creating-a-project/ Description: This guide shows you how to create a new project in Valsight, including configuring the project name, business key, and time settings. Create a new Valsight project, configuring its name, business key, description, and time horizon. ## Steps ### Open the project overview Open the **Project overview** (home page). ### Enter project details 1. Click **Add** in the upper right corner. ![image-20260303-144531.png](./images/6764101638.png) 2. Enter a name for your project in the **Name** field. 3. Enter a unique identifier in the **Business Key** field. 4. Optionally, add a description in the **Description** field. 5. Click **Next**. ![image-20260303-144619.png](./images/6761709591.png) ### Set the time horizon 1. Select the **Horizon Period** (Year, Quarter, or Month). 2. Enter the start date in the **From** field. 3. Enter the end date in the **To** field. 4. Click **Create**. > **Weeks are not offered here.** The Horizon Period list in this dialog is always Year, Quarter and Month. A project that should run on ISO 8601 weeks is created like any other and switched afterwards under **Divide years into** in [Project Settings](/project-settings/). Make that switch before you build on the project: it rebuilds the Time dimension, deleting the Quarter and Month levels and clearing every model and workspace horizon override. ![image-20260303-144700.png](./images/6762266652.png) ## What you have done The new project appears in the Project overview. You can now add data sources, models, and simulation workspaces to it. ## Related * [Business Key](/business-key/): the purpose and naming conventions for business keys * [Project Settings](/project-settings/): detailed configuration options after project creation * [Data Upload & Import/Export Overview](/data-upload-import-export-overview/): import data into your project --- # Creating a Workspace URL: https://docs.valsight.ai/creating-a-workspace/ Description: To create a workspace, navigate to the list of workspaces by selecting "Workspaces" in the main menu on the left. You will see a list of all workspaces you h… To create a workspace, navigate to the list of workspaces by selecting "Workspaces" in the main menu on the left. You will see a list of all workspaces you have access to. To **create a new workspace,** click the ‘Add’ - button in the top right corner. You will have to give your new workspace a name and select the model and scenario on which to base the workspace. The selected scenario defines the data baseline that will be used as the basis for all simulations you create in your new workspace. After clicking "Create", your new workspace will appear in the overview. ![image-20230602-131125.png](./images/5149196478.png) Via the three-dot menu, you can access the settings of a workspace. You can change and adjust all properties, most importantly the **simulation horizon**. This setting defines the time interval that will be used for all your simulations. The second step of that dialog holds the rest of them: * **Default Baseline:** the project baseline the workspace calculates on. It is chosen when the workspace is created, but it can be changed here afterwards, which re-bases the whole workspace. * **Hide technical nodes** and **Show scenarios in model editor**, which control what the workspace shows. * **Responsive Chart Text Size**, the per-workspace override described on [Responsive Chart Text Size](/responsive-chart-text-sizes/). ![image-20230602-131324.png](./images/5150375977.png) Open your workspace by clicking on its name. You will find it empty without any charts or assumptions.You can continue by populating your workspace with new tabs, charts, assumptions, and scenarios. --- # Creating and Configuring Models URL: https://docs.valsight.ai/creating-and-configuring-models/ Description: This guide shows you how to create a new, empty model inside an existing project and open it on the model canvas, ready for further configuration. Create a new, empty model inside an existing project and open it on the model canvas, ready for further configuration. ## Prerequisites * You have access to an existing project in **Valsight**. * You have permission to create models in that project. ## Models and submodels Once a model has been created, nodes can be built inside it to represent business logic. When a model uses nodes from another model, the two become linked. The referenced model is then understood as a **submodel**: a smaller, focused part of the overall model structure. Submodels are regular models; the term reflects their role in the structure, not a different object type. For an overview of when and why to use submodels, see [Models](/models/). ## Steps ### Open the project where you want to create the model Select the project from the home or project overview. ### Open the models section inside the project Navigate to the icon labeled *Models* on the ***Valsight Menu***. ### Create a new model Select **Add model** in the top-right corner of the header. ### Enter the model details Provide a model name and, optionally, a short description. If this model should be able to use nodes from another model, go to step 2 of the dialog, **Submodel Configuration**, and select the models whose nodes should be available here. You can skip this and configure submodels later by editing the model, where the same setting is step 3, **Configure Submodels**. The two dialogs number and name it differently. ### Confirm creation Select **Create** to add the model to the project. ### Open the model canvas Select the newly created model by clicking its name or double-clicking its tile. ## What you have done You see an empty model canvas. The model is now created and ready for adding nodes, calculations, and structure. ## Set a default unit for a model Step 1 of the **Edit Model** dialog carries a **Default Unit** setting. Whatever you choose there becomes the unit of every node created in that model from then on, which saves setting the same unit by hand on node after node. Switch on **Compound Unit** to build one out of two units and an operator, for example `EUR / Piece`. The setting is a real usage of that unit: a unit chosen as a model's default cannot be deleted at project level while the model still refers to it. ## Configure submodels on an existing model You can add or change submodel connections at any time after a model has been created. 1. Open the **Models** section of the project. 2. Find the model you want to configure and open its **Edit** dialog via the model “…” menu. 3. In the **Edit Model** dialog, go to step 3: **Configure Submodels**. 4. Select the models whose nodes should be available in this model. 5. Confirm the changes. The selected models are now linked, and their nodes are available for use in this model. ## Related * [Add Nodes to a Model](/creating-nodes/) * [Define Calculations for a Node](/define-calculations-for-a-node/) * [Structure Driver Models](/structure-driver-models/) --- # Creating and Downloading an Export URL: https://docs.valsight.ai/creating-and-downloading-an-export/ Description: In order to create and download, save or share a scenario export, you must create an export first. This export will be saved in the Export Manager and can th… In order to create and download, save or share a scenario export, you must create an export first. This export will be saved in the Export Manager and can then be downloaded and managed. You can either create an export via the [**Scenario Export in the Scenario Manager**](/data-upload-import-export-overview/) or directly within the Export Manager. Start by clicking the blue ‘Create Export’ button in the top right corner. ![Group 10.png](./images/5552701445.png) ## Select a scenario To create an export from within the Export Manager, select the workspace and the desired scenario to export. To export the nodes and calculations without simulations, simply select the scenario ‘Basic’. ![image-20240606-183646.png](./images/5559156788.png) > Alternatively, you can create an export directly from the Scenario Manager. View the documentation [**here**](/data-upload-import-export-overview/) to view how. Then chose one or multiple nodes which should be exported with the scenario context. You can select all nodes, single nodes or custom nodes using templates. ![image 5.png](./images/5551685648.png) ## Export settings (Optional) select a name, description and define the exports storing option. A custom name and/or description can be added in order to find it easier later on. This is recommended for exports which will be shared with another project. The name will be auto-generated through a combination of project name, workspace and scenario name if left blank. **You can skip this step altogether if you only wish to download the export.** ![image 6.png](./images/5551521816.png) ## Creating the export You can now go ahead and create the export. Note that this is not yet triggering a download but pre-calculating, creating and saving an export which can then be downloaded. > You will be able to chose a format and download the export after it has been successfully created. Depending on your project’s size, this can take a while. As this process is being handled in the background you can go ahead and continue working elsewhere. You will be notified as soon as your export has been created As soon as you trigger the creation of an export, it if will appear in the export manager, along with it’s creation status. ![Group 9.png](./images/5551784005.png) ## Downloading the export The download can either be downloaded via the exports ‘download’ button: ![Group 11 (1).png](./images/5565612043.png) Or directly via the green callout message on the top of you screen which will appear as soon as the export has been successfully created: ![Group 9 (1).png](./images/5552635925.png) The available [**download options**](/export-formats/)[are](/export-formats/) Excel and CSV. It is also possible to create an OData link to the export to i.e. connect an external dashboard with this Scenario. Please view the [**export format**](/export-formats/) documentation to learn more about various OData link types and how they work. ## Downloading a specific version ![image-20240606-163025.png](./images/5558960149.png) If you wish to download a specific [**version of an export**](/versioning-of-exports/), click on the export’s name to navigate to its version history. Here, you can select a specific version, the latest or an older one. Click the download button and select a download format just like on the export overview page. ## Building a URL to download the latest version of an export You can programmatically download the latest version of an export by constructing a URL. This allows external tools or scripts to access the most up-to-date version of your export directly. ### URL format The URL structure is as follows: `[appUrl]/v1/scenarioExports/[exportID]/exportLatestAsCsv/` * `[appUrl]`: Replace this with the base URL of your Valsight instance (e.g., `https://example.valsight.com`). * `[exportID]`: The unique identifier for the export. ### Finding the Export ID To locate the **Export ID**: 1. Navigate to the **Export Manager** in the application. 2. Hover over the **download button** next to the desired export. 3. The Export ID is displayed in the tooltip or URL preview, as shown in the example below: * Example ID: `123456` * Complete URL: `https://example.valsight.com/scenarioExports/12345/exportLatestAsCsv` ![image-20241212-122945.png](./images/5861310495.png) ### Important notes * **Use the Export ID, not the Version ID**: * The Export ID ensures that the latest version of the export is always downloaded. * Using a Version ID would link to a specific, potentially outdated version. * **Authentication**: The caller needs **edit** permission on the export, not merely read access, so a read-only service account cannot pull one. A tool without a Valsight session can authenticate with HTTP Basic authentication; without it the request is answered with 401. ## Related * [Export Manager](/export-manager/) --- # Creating Assumptions URL: https://docs.valsight.ai/creating-assumptions/ Description: Assumptions describe an encapsulated change on top of the base data in your Model. They can be used to describe the change in the development of a value driv… Assumptions describe an encapsulated change on top of the base data in your Model. They can be used to describe the change in the development of a value driver or to describe the effect of a planned or discussed measure. Assumptions describe a potential alternative and group all changes related to the issue, typically affecting multiple line-items in the model. ## Creating assumptions In Valsight, you can create assumptions in the Scenario Manager by clicking the ‘Plus’ button and selecting “Create Assumption” from the resulting dialog. ![image-20230531-095014.png](./images/5479399509.png) You will find the new assumption listed in the Scenario Manager and can select it to display its details. The detail view allows you to edit the name and description and gives an overview listing all line items and their effects over the years. This allows you to get a quick grasp of the Assumption Impact, without having to build detailed Charts. ## Editing assumptions Using the three-dot menu of an assumption next to its name allows you to: * **add** a line-item to the assumption * **edit** the assumption. This will open the detail page of the Assumption and is equivalent to selecting the Assumption in the overview list * **duplicate** the assumption. This will create a copy including all Line-Items. The dialog has a mandatory **Target Workspace** field, so the copy can go to another workspace, not only the current one. Duplicating a single line-item offers a **Target Assumption Group** picker as well, but it is disabled unless the target workspace is the current one * **save** the assumption as a template * **upload** an XLSX file to base the assumption on or download the XLSX file of the current assumption * **manifest** a version of the assumption or return it to a previously manifested version * **deleting** the assumption. This will delete the assumption with all its Line-Items When hovering over the name of an assumption or a line-item in the list, two small arrows appear on the left. You can use these to rearrange the order of your assumptions or to sort the line items in an assumption. Sort your assumptions according to topics or other properties like priorities, whatever fits your purpose best. You can also do this by dragging and dropping assumptions to its new place. --- # Creating Charts URL: https://docs.valsight.ai/creating-charts/ Description: Add a chart to a worksheet, point it at the data you want, and reuse a configuration you already have. Add a chart to a worksheet and point it at the data you want. How to make it read well afterwards is covered in [Formatting Charts](/chart-configuration/). ## Start here if you want to: | If you | Go to | | --------------------------------------------------------- | ------------------------------------------------------------------------ | | Choose which data a chart shows, and at which aggregation | [Data Display in Charts and Tables](/data-display-in-charts-and-tables/) | | Reuse a chart configuration you already built | [Chart Templates](/chart-templates/) | | Choose which chart or tile fits your data | [Chart Types](/chart-types/) | | Sort, scale or format a chart you already have | [Formatting Charts](/chart-configuration/) | ## How charts work Charts are the key mechanism in Valsight to display and interact with your data. They are always part of a simulation workspace, so what they display is based on a model and on the scenarios configured in that workspace. Charts can be arranged across multiple tabs, with several per tab in a dashboard-like layout. ![A worksheet with several charts laid out across a tab](./images/5147885610.png) Three things are worth knowing before you build one: * **Charts are calculated, not stored.** Every chart is derived on the fly from the underlying value driver logic and the configured scenarios. Changing a scenario, the model or the data recalculates it. When the workspace is set to refresh manually, that recalculation waits for you: the chart keeps its last result and marks itself as potentially outdated until the workspace is refreshed. See [Workspaces](/workspaces/) for the refresh setting. * **Axes and filters describe the data.** You say what a chart should display by setting its axes and, optionally, its filters. The axes depend on the chart type and define the two dimensions used to visualize the data, for example which information sits on the x-axis and which property groups the data series. Filters narrow that further, to a subset. * **Three dimensions are special.** *Scenarios*, *years* and *nodes* should never be aggregated in a chart. Each has to be either placed on an axis or configured as a filter. ## Adding a chart 1. Either add a tab with the plus button at the far left of the tab bar, or add a chart to an existing tab with the **Chart** button in the header. 2. Select a chart type. See [Chart Types](/chart-types/) for which one fits your data. 3. Select a scenario. 4. Select a node. To start from a configuration you already built rather than from scratch, see [Chart Templates](/chart-templates/). ## What you can set on a chart Select a chart and the chart editor opens in the panel on the right. If it is already open, selecting a chart shows that chart's properties; otherwise select the chart and click the pencil icon. The preview beside the editor is stretched to fill the space. Use the **Real Size** toggle to see the chart at the size of the tile it actually sits in, which matters for the chart types whose text scales with the tile, see [Responsive Chart Text Sizes](/responsive-chart-text-sizes/). ![The chart editor open beside a chart](./images/5148377129.png) | Setting | What it does | | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Chart type** | The data display property switches the chart type. Left to right: line, column, bar, area, mixed, waterfall, table, bubble, pie. See [Chart Types](/chart-types/) for which to pick. | | **Title** | Left empty, a title is proposed from the displayed nodes, years and scenarios. It can be overridden with a custom name. | | **Axis settings** | Define the dimensions the chart shows, for example which dimension sits on the x-axis and which one groups the data series. Any dimension in the system can be selected, though some combinations hold no data and will display nothing. | | **Levels and filters** | Restrict the chart to a subset of data. Every dimension used as an axis automatically gets a multi-select filter containing all values, except on a KPI chart, which starts with two level values selected instead. Add more with **Add Filter**, choosing a dimension and a level. | | **Comparison** | Compare any single data point against another, as a delta or a percentage. See [Delta Comparisons](/scenario-time-or-dimension-level-comparison-delta/). | For how to choose what the axes actually show, including aggregation and combining nodes of different dimensionality, see [Data Display in Charts and Tables](/data-display-in-charts-and-tables/). ## Copying a chart Charts can be copied from the settings button at the top right of a chart. Select **Move or duplicate** to open a dialog offering both: **Move Chart** takes the chart off its current sheet, **Duplicate Chart** leaves the original in place. Either way you then choose a **Target Workspace** and a **Target Sheet**, so a chart can be sent to a different workspace and not only to another sheet of this one. Slider and Scenario Manager tiles are the exception: they cannot leave their workspace, so for those the workspace picker is not shown. The same settings menu also holds **Save as template**, **Export as...**, **Calculation info**, which opens the chart's raw calculation output in a new tab and is what support will ask for when a number looks wrong, and **Delete**. ![The Move or duplicate option in a chart's settings menu](./images/5115773013.png)![The dialog for choosing the target sheet](./images/5115773020.png) ## Data format You can display numbers inside the chart, override axis settings, and configure whether a legend is shown and whether null values are hidden. ![The data format settings in the chart editor](./images/5148147771.png) ## Related * [Chart Types](/chart-types/): which chart or tile fits your data. * [Data Display in Charts and Tables](/data-display-in-charts-and-tables/): what a chart shows, and at which level of aggregation. * [Chart Templates](/chart-templates/): reuse a configuration instead of rebuilding it. * [Formatting Charts](/chart-configuration/): [stacking and stack totals](/stacking-and-stack-totals/), [styling data series, columns and rows](/styling-data-series-columns-and-rows/), scales and axes, table styles, and [responsive text sizes](/responsive-chart-text-sizes/). --- # Creating & maintaining dimensions URL: https://docs.valsight.ai/creating-maintaining-dimensions/ Description: Navigate to the Dimension Manager and create a new Dimension. Navigate to the Dimension Manager and create a new Dimension. ![1 and 2.png](./images/5094206980.png) ## Creating a dimension To fill a dimension with values, there are two possible solutions: Creating the dimensions manually from the dimension manager or uploading an XLSX sheet to let Valsight automatically create them. ## Create dimensions manually from dimension manager To create a dimension manually, head to the dimension manager via the navigation bar. ![Head to Dimension Manager.png](./images/5094206407.png) Here you will see an overview of all your existing dimensions. To create a new one, click the “Add” button in the top right corner. A pop-up window will open that enables you to enter a dimension name and description, and already add multiple levels to your dimension. In this example, the dimension shall be named 'Location' and consist of three levels: “Continent”, “Country”, and “City”. After entering the first level, press 'Shift + Enter', and the entry field for the next level will appear. ![name and levels.gif](./images/5094206560.gif) ## Adding level values The next screen after you confirmed the dimension name and its initial levels shows you that you have not yet entered any values for those levels. Therefore, the next step will be to fill the three first levels with content. 1. Click on the 'Add entry' button in the upper left corner. A drop-down menu will open. ![Add Entry.png](./images/5094206414.png) 1. Enter the name of the first level entry you want to add and click on 'Create value....' 2. Do the same for the second and third levels (for the third level you do not need to click on 'Create value....') 3. Click “Add” and the values will be added ![add entry.gif](./images/5094206567.gif) > **Create new values** > > To create new values for each level you need to enter the name of the value you want to enter and click on 'Create value....' or press enter. This is not necessary for the last level. ## Adding rows to levels Users are also able to add rows to the levels without uploading a new excel file. Rows can be added with the 'add entry' button. ![add entry row.gif](./images/5094206598.gif) This process is also possible with linked levels. ## Adding new level values To add a new level value, download the Excel file from the dimension page and add a new row with all of its levels. In this example, we add the city 'Peking' on the continent 'Asia' (Here in green). On upload, a prompt shows which new values will be added. ![image2020-3-19\_11-25-37.png](./images/5094206459.png)![image2020-3-19\_11-1-29.png](./images/5094206466.png) ## Moving a level value to another parent **Move to another parent** in a level value's menu re-parents it without an Excel round-trip. Three things are worth knowing: * The action is offered only for values **below the roughest level**. A value on the top level has no parent to move it to, so the menu item does not appear for it. * The dialog offers a list of the valid parent values to choose from, so you cannot type a parent that does not exist. * If the value being moved is the last one under its current parent, Valsight warns that ‘Moving this value to another parent will delete the current parent value. It is still referenced in some locations:’ and lists them. The move then empties, and so removes, the old parent. ## Deleting a level value A level value that is referenced in a node, a line-item or a data source can still be deleted, but not silently. The deletion prompt lists everything that uses it and asks you to confirm a **force delete**, which is why the message is ‘Level value(s) in use — force delete required’ rather than a refusal. One usage is absolute: a **level link to another dimension** blocks the deletion outright and cannot be forced. Clear the link first. The prompt shows all items you would be affecting, so read it before confirming rather than after. ![2018-09-20\_14-16-43.png](./images/5094206718.png) ## Understanding usage of dimensions in a project As a project admin, a user is able to trace in which model and in which nodes a dimension and its levels are used. To do so, go to the Valsight settings, via the settings icon in the tabbar. From there, navigate to your project in the project list and use the “Show Dimensions” button. At the bottom of the details listed there, a usage report for the selected dimension can be opened. The following list shows the model, the node and the level in use. ![image-20231218-154247.png](./images/5315461259.png) ## Uploading a configured XLSX sheet For the second method, name the dimension "TutorialProduct" and the Level 1 "TutorialProductGroup". ![Snip V2 Adding a Custom Dimension 2.png](./images/5094206404.png) After creating the Dimension we want to configure its hierarchies. Select "configure Hierarchies" in the top right to do so. ![Snip V2 Adding a Custom Dimension 3.png](./images/5094206581.png) Our dimension has two hierarchies or levels. The first one is "TutorialProductGroup" which we created together with the dimension. This dimension contains the product group each product is in. The second level is named "TutorialProduct", containing the different product names. To create it select "Add Level" in the top right. Now name the new level "TutorialProduct" and insert it in the last position, since it is our lowest ranked level. ![Snip V2 Adding a Custom Dimension 4.png](./images/5094206595.png) Now that our hierarchies are set up, we can select "Download Excel" on the top right in the previous menu. This will give us an XLSX file into which we can enter our level values. ![Excel Dimensions Empty v2.15.png](./images/5094206429.png) Please transfer the following values into the new XLSX file: | TutorialProductGroup | TutorialProduct | | -------------------- | --------------- | | Group A | Product A | | Group B | Product B.1 | | Group B | Product B.2 | The finished XLSX file should look like our example. ![Excel Dimensions filled v2.15.png](./images/5094206432.png) The next step is to upload the updated XLSX file. To do so, select the "Upload Excel" button next to "Download Excel". Then select the "TutorialProduct.xlsx" file, click on "Preview" and lastly on "Confirm". ![Snip V2 Adding a Custom Dimension 5.png](./images/5094206411.png) Once the file is uploaded your "TutorialProduct" dimension should look as follows: ![Dimension TutorialProduct v2.15.png](./images/5094206422.png) ## Creating or configuring the level hierarchy If you want to create a dimension-level hierarchy, use the configure hierarchy button on the dimension page. ![image2018-9-20\_11-47-53.png](./images/5094206991.png) You have the possibility to add higher or lower-level values. We will create the higher level region. We can either use the add level button or the “ACTIONS” drop-down. ![2018-09-20\_11-57-20.png](./images/5094207030.png) After moving back to the location dimension screen, we use the action dropdown to rename the regions and move the items accordingly. An animation shows the creation of the Americas and moving the USA to the region. ## Extending the base data We can now extend the base data in our actuals sheet to actually include the product information. | Year | TutorialProduct | Price | Volume | | ---- | --------------- | ----- | ------ | | 2018 | Product A | 10 | 500 | | 2018 | Product B.1 | 20 | 250 | | 2018 | Product B.2 | 5 | 250 | We replace the data file in the "Data source" used for your model's base data by doing the following: First, open the submodel you created in [Create a new Model](/creating-and-configuring-models/). Then select "Upload Data" in the top right. ![Snip V2 Adding a Custom Dimension 6.png](./images/5094206441.png) This will open the data upload wizard showing all data sources. Since we want to update the "DemoContent" data source, we select "Upload" next to it. ![Snip V2 Adding a Custom Dimension 7.png](./images/5094206450.png) Now choose “Working with Dimensions” and select "Check Content". ![Snip V2 Adding a Custom Dimension 8.png](./images/5094206435.png) Valsight now shows you a preview of the new data structure. As you can see "TutorialProduct" was added and will be connected with the custom dimension you created earlier. You can hit "Validate Content" once you are familiar with the new data structure. ![Snip V2 Adding a Custom Dimension 9.png](./images/5094206438.png) Finally, you'll receive information on what changed. After hitting "Confirm" your data source is updated! ![Snip V2 Adding a Custom Dimension 10.png](./images/5094206474.png) Without changing a single formula, we have changed the dimensionality of the model! Now we can check the preview data functionality by selecting "Data Preview" in the "Functions" selection (upper left corner) to verify that all data is now calculated on the product level! ![Snip V2 Adding a Custom Dimension 11.png](./images/5094206481.png) --- # Creating & Managing Workflows (For Admins) URL: https://docs.valsight.ai/creating-managing-workflows-for-admins/ Description: Bildschirmfoto 2025-02-03 um 16.07.28.png Workflows are project management tools that let departments collaborate on shared scenarios through defined sequential steps. This guide covers how administrators create, configure and manage them. ![Bildschirmfoto 2025-02-03 um 16.07.28.png](./images/5933465609.png) Workflows are Valsight's internal project management tools that enable a smooth collaborative process across multiple business units and levels. We recommend Workflows for larger, cross-departmental projects such as multi-year planning and forecasting cycles. A Workflow defines how a project works. It is reusable, which is particularly useful for recurring projects such as forecasting. ## How workflows work A Workflow allows multiple teams with multiple Workspaces (i.e. EU, DE, and EN) to work on the same Scenario(s) (i.e. MYP – Base Case & MYP – Best Case) in a pre-defined order (i.e. EU – Base Assumptions -> DE & EN Measures -> EU – Consolidation). It allows Teams to view, review and build upon previous assumptions, measures and simulations, submit their own as well as eases the control and review process of these. ## Navigating workflows The Workflows can be found under the ‘Workflows’ icon in the navigation bar on the left. The Workflow page consists of two tabs for an easier management; ‘Ongoing’ & ‘Completed’. ![image-20240712-112317.png](./images/5617090653.png) **Workflows States:** 1. Draft – A Workflow which has been created but not started yet. Can still be edited. 2. Active – A Workflow which has been started and is currently ongoing. Only basic properties such as name can be edited. 3. Completed – These are Workflows which have been ended once all Workflows steps have been set to ‘Done’. 4. Canceled – Workflows which have been stopped without all steps set to done. ![image-20240712-112651.png](./images/5617647699.png) > * Once a Workflow has been started, no new steps can be added. > * Both completed and canceled Workflows can be duplicated and reused later. ## Creating a new workflow Click on ‘Create a Workflow’ to open the configuration dialogue. Here you will have parameters which you can set: **Base Settings:** *General settings for a basic Workflow* * **Name:** The name of the flow. It is recommended to name it so that it is clearly understandable what it is. Keep in mind that individual contributors will have to chose it when importing or submitting their Scenarios, i.e. company forecast. The Scenario names that you choose in the setup of your Workflow will define the Scenarios you want people to collaborate on in your Workflow. Each user will be able to add assumptions to these Scenarios. Other users will be able to see these changes and built upon them in their own workspace. ![image2020-10-12\_16-36-59.png?version=1\&modificationDate=1602513419342\&cacheVersion=1\&api=v2\&width=340\&height=250](./images/5600149542.png) > *As Workflows can be repeated, it is best to not include version specifics in the name (i.e. 2024 or v1). Use the Version field for this (see below).* * **Create Scenario:** Starting a Workflow will create one or more Scenarios in each chosen workspace. Individual contributors will then be able to submit their measures and assumptions in these Scenarios. To name the Scenarios, type the Scenario name followed by a comma (,). Press enter to confirm. At least one Scenario name is required, and two Scenarios in the same Workflow cannot carry the same name. You may also enter the name of a Scenario that already exists: it is included in the Workflow and created in every workspace that does not have it yet. * **Description** * **Version:** Required. Because Workflows are repeatable, the version is what tells one run of a Workflow apart from the next, i.e. ‘Q1’, ‘2024’, ‘FC 3+9’, ‘v1’… The ‘Create’ button stays disabled while the field is empty. > **Workflow Scenarios are linked by name.** A Scenario belongs to a Workflow because its name matches one of the Scenario names configured here, not through a hidden reference. Renaming a Scenario in the [Scenario Manager](/scenario-manager/) therefore drops it out of the Workflow, and giving an unrelated Scenario the exact name of a Workflow Scenario pulls it in. Valsight raises a ‘Workflow Link/Unlink’ confirmation before saving such a rename, but the rename itself is allowed. ![image-20240712-112516.png](./images/5617254524.png) **Advanced Settings:** *These are optional settings which are necessary in case you wish to create new workspaces with starting this Workflow. I.e. a consolidation workspace.* * **Associated Model:** Which model should the new workspaces be based on. * **Associated Baseline:** Which baseline should these workspace use. > The two are optional only as a pair: leave both empty, or set both. A model without a baseline blocks the creation of the Workflow with ‘Please choose a corresponding Baseline’. Changing the model clears the baseline you had already picked, so choose the model first. > New workspaces will be named after the Workflow step. To create a new workspace, simply leave the ‘Associated workspace’ field empty when creating a Workflow step (see below). ![image-20240712-112537.png](./images/5617647692.png) ## Configuring the workflow A Workflow consists of multiple Workflow steps. These have a specific order and can be dependent from one another. To configure the Workflow, click on the Workflows name once it is in ‘Draft’ stage. > Adding and editing steps is reserved for project admins. Everyone else finds the step creation button unavailable, with the tooltip ‘This function is only available to project admins’, and the step dialogue opens behind the warning ‘You do not have sufficient permissions. Only project admins can add or edit workflow steps.’ **Workflow step stages:** 1. **Open:** The step has not been submitted yet 2. **Preview:** The step has been submitted. If necessary, it can be reviewed now. 3. **Review:** The step has been reviewed and promoted. If necessary, it can be reviewed a second time by another reviewer. 4. **Done:** The step is reviewed and completed. No further changes are possible. Click on the ‘Create Workflow Step’ button. To create a step, give it a name (i.e. ‘EU Base Assumptions’), optionally a description, and assign it a workspace. The description is shown with the step’s submissions, which read ‘No description’ when you leave it empty. Not every workspace is accepted: * **All steps must share one model tree.** A step’s workspace has to be based on the Workflow’s model, or on a super- or submodel of it. A workspace from another model tree is refused with ‘All connected steps must be associated with workspaces basing on the same model’. * **Template workspaces are not allowed** in Workflows and are rejected when you confirm the step. Leave the ‘Associated workspace’ field empty to have the Workflow create a new workspace for this step. This works only if the Workflow itself has both an Associated Model and an Associated Baseline set under Advanced Settings (see above). Without them the confirm button of a new step stays disabled, and the tooltip asks you to either select a workspace or configure the Workflow with a model and a baseline. ![image-20240712-112740.png](./images/5616763049.png) Select a previous step if necessary. This will determine, which Workflow steps this step is dependent on. The dependency gates promotion, not sharing. Contributors in this step can share their Scenarios whenever they like, but a Scenario only leaves ‘Preview’ once it has been shared **and** every input step has its Scenario of the same name on ‘Done’. Importing a previous step does not satisfy the dependency. Until it is met, Valsight refuses the status change with ‘You cannot update the status. Ensure a scenario is submitted and that all previous steps are set to Done.’ ![image-20240712-112803.png](./images/5617352794.png) **Configure Permissions:** Permissions are assigned per state, not per step. The ‘Configure Permissions’ tab opens the ‘Configure state permissions’ dialogue: a table with one row per state and a ‘Users & Groups’ field on each row. ![image-20240712-112841.png](./images/5617451076.png) Each row names the users and user groups who may move the step into that state. There are three rows, ‘Open’, ‘Preview’ and ‘Review’. ‘Done’ has no row, because no one holds rights on the final state. Leave a row blank for states which do not need to be handled by specific users, but see [Email notifications](#email-notifications) for what a blank row does to the recipient list. Permissions are the one part of a step that stays editable after the Workflow has started: no new steps can be added, but new step permissions can still be assigned. Once the Workflow is configured, it can be started with the ‘Start’ button in the header of its Configuration page, or through the three-dot menu in the Workflow overview. This will create all Scenarios in all associated workspaces as well as create any new workspaces. **Step Order:** Workflow steps can be configured by the admin, and their order will be reflected in both the Workflow's submissions page for an improved overview and in the workspaces. If a workspace has more than one workflow step assigned, arranging the steps in the correct order helps users navigate them more easily within the workspace. Clicking on the sort button, right next to the search bar, will open the sorting dialogue: ![Bildschirmfoto 2025-02-03 um 16.12.13.png](./images/5933170697.png)![image-20241101-141306.png](./images/5796593681.png) Workflow steps are sorted alphabetically per default. The ‘Sort order’ dropdown offers three modes: ‘Manual’, ‘Alphabetical - ascending’ and ‘Alphabetical - descending’. ‘Manual’ is the only one that lets you arrange the steps freely, so it is the mode to pick when the order above matters. ## Managing ongoing workflows Open a Workflow's submissions page to view its progress by clicking on an active Workflow's name. ![Bildschirmfoto 2025-02-03 um 16.07.28.png](./images/5933465609.png) The table has one row per Workflow step and one column per Scenario. Click a submission's name, not the status tag beside it, to open [its details](/submission-details-and-activity/): the status, the workspace it came from, the full history of what has happened to it including every comment, and the actions to promote or demote it. The header of the submission details carries a third action, ‘Update Submission Data’. It pulls the contributor’s Scenario as it stands right now and shares it as a new version on top of what was shared before, so a submission is not frozen once it has been made. It is available while the Workflow is running, and it fails with ‘The scenario "…" is missing from the workspace "…"’ if the contributor has renamed or deleted the Scenario in the meantime. The same update is available in bulk from the ‘Share Workflow Steps’ dialogue in the Scenario Manager. > As an admin, you can demote a Workflow step from done to review. This is only possible for admins and will also demote subsequent steps which were on done back to review. ## Reviewing and consolidating steps and scenarios To review a submission, open the subsequent steps workspace, navigate and to the Scenario manager. If a previous step has been submitted, the Workflow icon will be highlighted in orange. Click on it and open ‘Import Previous Steps’. Select the current Workflow and the step that you are in and select all previous steps. ![image-20240712-113029.png](./images/5617549391.png) You can then check the numbers as well as any charts that you might have. If everything looks right, go back to the Workflow icon, open ‘Share Workflow Steps’ and promote the steps to the next stage. Alternatively, you can promote the steps from the Workflow's submissions page. > **Consolidating and doubling assumptions:** If you have two steps which have the same previous step, they will end up importing the same assumption (I.e. inflation). When consolidating these back together into a new or existing workspace, the two assumptions will **not** be doubled. Valsight detects that it is the same assumption and will calculate it accordingly, so that no further action has to be taken. > > **If you consolidate the assumptions into the original workspace,** the workspace will still have the original assumption (i.e. inflation). In this case, the assumption has to be unchecked to prevent doubling, as the shared Scenarios will already carry the inflation in them. ## Closing a workflow Once all Workflow steps and all Scenarios have been submitted, reviewed (where necessary) and promoted to done, the Workflow can be completed by clicking the ‘Complete’ button in the header of its Configuration page or through the three-dot menu in the Workflow overview page. It can then be viewed under the ‘Completed’ tab. ![Bildschirmfoto 2025-02-03 um 16.09.22.png](./images/5933006854.png) **Stopping a Workflow:** A Workflow that should not run to the end can be stopped instead of completed. Use the ‘Stop’ button and confirm ‘Are you sure you want to stop this workflow?’. The Workflow moves to ‘Canceled’ and joins the completed Workflows under the ‘Completed’ tab. Like a completed one, it can still be duplicated and reused later. **Duplicating a Workflow:** ‘Duplicate’ in the three-dot menu of the Workflow overview opens the ‘Duplicate Workflow’ dialogue. You may give the copy its own version there, or leave the field empty and let Valsight generate one. The copy takes the name of the original with ‘ Copy’ appended and lands in ‘Draft’, so you can adjust its steps before starting it. ## Deleting workflows and steps Both deletions are gated on the state of the Workflow. * **Deleting a Workflow** is done from the three-dot menu in the Workflow overview. It is refused while the Workflow is active, with the message ‘This Workflow’s current status is "…". You cannot delete it.’ Complete or stop the Workflow first. * **Deleting a step** is only possible while the Workflow is still in ‘Draft’. Afterwards you get ‘This workflow’s current status is "…". You cannot delete any step inside.’ When the deletion is allowed, Valsight warns that deleting the step also removes it from the input list of every other step, so any dependency on it disappears with it. A workspace taking part in an ongoing Workflow cannot be deleted either. The refusal names up to three of the blocking Workflows, plus a count of the remainder if there are more, and asks you to complete them first. ## Email notifications There are events that trigger e-mail notifications. These events include: 1. A new comment has been submitted on a step 2. Data has been updated 3. The status of a step changes (promoted or demoted) The recipients are all users who hold a permission on one of the step’s states. The final state, ‘Done’, carries no permissions and is skipped. > If one of those states has no user or group assigned, every project admin, that is every holder of write permission on the project space, is notified in its place. Leaving step permissions blank mails all project admins rather than nobody. The one who triggered the action will not be notified. Mail goes out on a ten-minute cycle rather than immediately, and it is skipped for anyone who has ticked ‘Disable e-mail notifications’ on their user profile. If nobody on a Workflow ever receives these, e-mail is probably not switched on for your Valsight installation; ask your administrator. --- # Creating Nodes URL: https://docs.valsight.ai/creating-nodes/ Description: This guide shows you how to add nodes to an empty model canvas so you can start building the basic structure of your model. Add nodes to an empty model canvas so you can start building the basic structure of your model. ## Prerequisites * A [model is already created](/creating-and-configuring-models/) in **Valsight**. ## Steps ### Open the model Make sure the model you want to edit is open and the canvas is visible. ### Start adding a node Select the **Node** button in the action bar at the bottom of the canvas. ### Choose the node type The Node button opens a menu offering **Standard node**, **Simulation node**, **Data node** and **Validation node**. Pick one and the placement mode arms. For the rest of the session the button remembers your choice and arms it directly, so the menu only reappears if you open it yourself. ### Place the node on the canvas Move your cursor to the desired position and click to place the node. You can place multiple nodes in succession while the placement mode is active. To cancel placement, right-click or press **Esc**. The node you place is selected automatically, the Node Editor switches to its Object tab and the name field takes focus, so you can type the name straight away. ### Set the node name Enter a clear and unique name (for example, `Revenue`). A node name may not contain a single quote. Formulas reference nodes by wrapping the name in single quotes, as in `'Revenue'`, so an apostrophe inside the name would break the reference. Entering one is rejected with "Single quotes are not allowed in node names." ### Add a description (optional) Enter a short description to clarify the node’s purpose. ### Review and adjust the unit Check the **Unit** section and change it if the default unit does not match the node’s meaning. ### Repeat for additional nodes Add further nodes as needed (for example, `Price` and `Volume`) using the same steps. ## What you have done The model canvas now contains multiple nodes. Each node appears as a separate element and can be selected and edited individually. ## Related * [Nodes](/nodes/) * [Define Calculations for a Node](/define-calculations-for-a-node/) --- # Creating Sticky Notes & Frames URL: https://docs.valsight.ai/creating-sticky-notes-frames/ Description: The Annotations feature enhances collaboration in the Valsight Model Editor by allowing users to visually comment on, organize, and highlight areas of a mode… The **Annotations** feature enhances collaboration in the **Valsight Model Editor** by allowing users to visually comment on, organize, and highlight areas of a model. It provides a clear and flexible way to communicate logic, context, or suggestions directly within the modeling environment. Whether clarifying a calculation, marking key nodes, or guiding team members through a complex model structure, annotations help streamline collaboration and support model transparency. ## Key benefits With Sticky Notes & Frames, users can: * Add **contextual notes** directly on the canvas using customizable sticky notes * Use **colored frames** to group related areas of a model * Easily **toggle visibility** of all annotations to reduce visual clutter * **Reposition, edit, and delete** annotations freely as the model evolves * **Reuse annotations** across models and projects via copy and paste ### Example use case In a car manufacturing scenario, the finance team might use a **frame** to highlight all nodes related to “EV production cost drivers” and add **sticky notes** to explain assumptions for battery pricing. This helps ensure consistency across departments reviewing the same model structure. ## Setup and usage ### Recommended preparation To use annotations meaningfully and effectively: * Use **clear, concise naming** for frames and comments to enhance readability * Place annotations **near relevant nodes** to provide immediate visual context * Avoid excessive overlapping of annotations to maintain a clean canvas * For multi-user environments, establish internal guidelines for color usage or note structure * Consider using visibility toggles during presentations or walkthroughs to focus the view ### Creating sticky notes & frames To create a sticky note or frame: 1. Open the **Model Editor** 2. Click **“Annotation”** in the **Create** section of the footer action bar, next to the “Node” button 3. Choose one of the following options: * **Sticky Note** * **Frame** * **Divider** Video: [Sticky Notes](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6175326235_Sticky-Notes.mov) #### Sticky note setup Choosing **Sticky Note** does not open a dialog. It arms placement mode, and the cursor becomes a crosshair. * Click once on the canvas to place the note. It is created immediately, at a fixed default size, in the first color of the model's palette, carrying the placeholder text **“Double-click to edit”** * Press **Escape** or right-click to cancel placement without creating anything * Set the text and color afterwards in the **Annotation Editor**, or double-click the note to edit its text in place * Notes display a **scrollbar** if the text exceeds the field height * Selected notes show a **dotted border** and can be moved freely #### Frame setup Choosing **Frame** arms placement mode in the same way. There is no dialog and no rectangle to draw. * Click once on the canvas to place the frame. It is created immediately, at a fixed default size, in the first color of the model's palette, named **“New Frame”**, with the name field focused so you can rename it straight away * Press **Escape** or right-click to cancel placement * Resize and reposition the frame afterwards by dragging it * Set the title, color, and optional background color in the **Annotation Editor** #### Divider setup Dividers behave differently from the other two types: choosing **Divider** opens a dialog instead of arming placement. 1. Choose **Divider**. The **Add Divider** dialog opens. 2. Enter a **name**. The field cannot be left empty; an empty name is rejected with “Divider name must not be empty”. 3. Click **Create Divider**. The divider appears as a vertical line with its name on a label at the bottom. To move a divider, drag its line or its label sideways. To rename or remove one, hover its label and click the **cog icon** to open the **Section Settings** dialog. There you can change the **Name** and click **Update**, or click **Remove this Section** to delete the divider. The cog icon only appears if you have edit rights on the model. ### Interacting with annotations * Click any annotation to select it and open its settings in the **Editor Panel** (top right) * For sticky notes: * Click **“Edit Text”** to modify content * For frames: * Edit **title, color, or background** * To remove an annotation, click the **trash icon** in the object or editor panel * To manage visibility: * Open the **Inspector**, select the **Model** tab, and use the **Show Annotations** toggle under **Canvas Display** to show or hide all annotations at once * This toggle is **user-specific** and does not affect other users Video: [Show-hide annotations](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6175162421_Show-hide-annotations.mov) ## Managing, configuration and limitations ### Supported configuration * Annotations include: * **Sticky Notes** with text formatting and color * **Frames** with title, border, and optional background color * **Dividers** with a name, splitting the canvas into sections * Annotations can be **moved**, **copied**, **edited**, **deleted**, or **hidden** * Annotations are compatible with **keyboard and mouse input**, supporting drag-and-drop positioning * Copy & paste functionality is supported: * **Within the same model** * **Across different models** * **Across projects** ![Copy paste annotations.png](./images/6175457310.png) ### Error handling and system limitations * Overlapping or excessive annotations may lead to visual clutter but do not affect model performance * If an annotation cannot be pasted (e.g., incompatible data), a clear **error message** is shown * Long sticky notes will automatically scroll rather than resize * Annotations are purely **visual aids** and do not affect the model’s logic or calculations ### Data synchronization and integration * All annotations are stored **per model** and saved with the model state * **Visibility settings are stored per user**, ensuring a personalized experience * **No special rights** are required: any user with model edit access can use and manage annotations * Annotations are preserved during **project duplication, import, or export** ## Summary **Sticky Notes & Frames** support clearer communication, better documentation, and more efficient teamwork within the Model Editor. With rich formatting, intuitive placement, and full copy/paste support, they allow users to: * Provide helpful comments directly in the canvas * Visually organize and explain model logic * Reuse and manage annotations across models * Reduce complexity by toggling visibility on demand This feature helps make even the most complex models more accessible, navigable, and team-friendly - essential for transparent and collaborative modelling. --- # Custom Views in the Model Editor URL: https://docs.valsight.ai/custom-views-in-the-model-editor/ Description: The Model Editor lets you display optional overlays that add contextual information directly on nodes or the canvas. These views are independent of model log… The Model Editor lets you display optional overlays that add contextual information directly on nodes or the canvas. These views are independent of model logic and can be shown or hidden individually. --- # Customizing URL: https://docs.valsight.ai/customizing/ Description: Valsight ships a standard product with very little need to customize the software, besides some look and feel options. Valsight ships a standard product with very little need to customize the software, besides some look and feel options. This article aims to give an overview about these options. | Area / Topic | Notes | Link(s) | | ------------------------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Colors | All colors that are used in charts can be edited to fit with your CI. | [Editing the color palette](/editing-the-color-palette/) | | Presentations / Snapshots | Presentations can include your logo and a textual footer (e.g. "Confidential"). |
  • Add a Logo to your Presentations
  • [Add a copyright or confidentiality notice](/add-a-copyright-or-confidentiality-notice/)
  • [Presentation Favorites Headline](/presentation-favorites-headline/)
| | Modelling / Units | Edit the available units, add new ones etc. | [Configure Units](/configure-units/) | | Simulation | Add custom impact columns to the scenario manager | Impact Columns | | Simulation | It is possible to add flags/dropdowns for assumptions, e.g. "Status". | Configuring Assumption Properties | | Number Style | Render negative numbers as (5) and show billions and millions with " and ' , | [Number Style](/number-style/) | --- # DATA URL: https://docs.valsight.ai/data/ Description: The DATA function references a data table (an uploaded dataset, such as an Excel sheet) directly from within a node formula. **Category:** [Data access](/data-access/) ## Overview The **DATA** function **references a data table** (an uploaded dataset, such as an Excel sheet) **directly from within a node formula.** Use this function when you need to bring uploaded data into your Valsight model. ## Syntax `DATA("DataSourceName", "TableName", "MeasureName" [, "Unit"])` **Example usage:** `DATA("Cost_Upload", "G&A_Upload", "Value")` *Tip: You can also insert DATA formulas using the Data button in the Function Editor.* ## Parameters | Parameter | Description | Type | Required | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | | **DataSourceName** | Name of the data source in double quotes (e.g. `"Model Data"`). | String | Yes | | **TableName** | Name of the table in double quotes (e.g. `"Gross_Sales"`). If the data source is an Excel Workbook, this is the sheet name. | String | Yes | | **MeasureName** | Name of the measure column in double quotes (e.g. `"Price"`). | String | Yes | | **Unit** | Optional unit or ratio of two units. For a single unit, plain double quotes work (e.g. `"EUR"`). For a ratio, each unit must be wrapped in single quotes (e.g. `"'EUR'/'Case'"`). | String | No | ## Using the data button You can also create the function using the **Data button** in the Function Editor. This allows you to select the data source, table, and measure from a dropdown menu instead of typing them manually. Video: [DATA](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6799818753_DATA.mp4) ## Output shape | Aspect | Behavior | | -------------- | ---------------------------------------------------- | | Dimensionality | Inherits the full dimensionality of the source table | | Values | The selected measure column becomes the node value | | Row count | Returns all rows from the referenced data table | ## Watch out * Each DATA node references exactly **one measure**. * If your table contains **multiple measures**, create separate DATA nodes for each. * The category columns in your uploaded data (e.g. Region, Product, Month) **must match the** [**dimensions and levels**](/creating-maintaining-dimensions/) configured in your project. * The **order of rows** in the result may differ from the source table. ## Examples ### Basic data upload **Prerequisite** An Excel Workbook in the required Valsight format has been uploaded in the data management of Valsight. **See also:** [Restructuring Data in Excel using Power Query](/restructuring-data-in-excel-using-power-query/) ![Excel worksheet with Cost Category and 2025 values, formatted as required for a Valsight data upload](./images/6798966791.png) ![Excel worksheet with Year, Cost Category, and Value columns after restructuring for upload](./images/6799851523.png) **Formula:** `DATA("Cost_Upload", "G&A_Upload", "Value")` **Result:** ![Data Preview of the resulting DATA node, showing G\&A costs by category for 2025](./images/6798245894.png) The node now contains the complete dataset with all dimensional detail. ### Using an explicit unit You can optionally define a **unit** for the returned values. `DATA("Cost_Upload", "G&A_Upload", "Value", "EUR")` This returns the same data but explicitly sets the node's unit to *Euro.* ### Using project variables [Project variables](/project-variables/) can be placed anywhere within any string parameter, as the full value, a suffix, or embedded in the middle, to dynamically reference data sources or tables. This allows scenarios to switch between different sources without changing the formula. | Pattern | Example | | ----------------------------- | --------------------------------------------------------------------------------------------------------------- | | Variable as full parameter | `DATA("$DataSourceName", "TableName", "MeasureName")` or `DATA("DataSourceName", "$TableName", "MeasureName")` | | Variable appended to a prefix | `DATA("Actuals_$Year", "TableName", "MeasureName")` | | Variable embedded mid-string | `DATA("DataSourceName", "Table_$Variable", "MeasureName")` | ## Related | Function | When to use instead | | ----------------------------------------------- | ---------------------------------------------------------------------------------------- | | [EXPAND](/expand/) | When your DATA node needs additional dimensional detail not present in the source table. | | [FILTER](/filter/) | When you need only a subset of the rows returned by DATA. | | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) | When you need to project historical DATA values into future periods. | --- # Data access URL: https://docs.valsight.ai/data-access/ Description: Use this category when you want to bring uploaded or source data into node formulas, or send data to an external service and return the result to the model. Use this category when you want to **bring uploaded or source data into node formulas**, or send data to an external service and return the result to the model. These functions connect your model logic to data outside the formula itself. ## Start here if you want to: * **Reference a measure** from an uploaded table * Connect data using the **Function Editor UI** * Send cube inputs to an **external service** and return a result cube ## Not here if you want to: * Filter, fill, pick, or rank data after loading it → see [Filtering & data shaping](/filtering-data-shaping/) * Reshape granularity → see [Dimensionality & hierarchies](/dimensionality-hierarchies/) ## Mental model * `DATA` returns values from a specific data table measure * `API_CALL` sends one or more input cubes to an external endpoint and expects a result cube in return ## Common patterns | Name | What it does | Formula | | ------------------------------ | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | Reference a data-table measure | Use when a node should represent a measure from uploaded or source data. | `DATA("DataSourceName", "TableName", "MeasureName")` | | Set the unit on a DATA result | Optional, use when you want to explicitly supply a unit. | `DATA("Model Data", "Gross_Sales", "Price", "EUR")` | | Use the UI to connect data | Use the **Data** button in the Function Editor to build the `DATA` call for you. | | | Call an external service | Use when logic or data lives outside Valsight and returns the result. | `API_CALL("https://externalServer.com/sumTwoNodes", ['Node A', 'Node B'], ["Year", "Country"])` | ## Functions in this category | Function | Description | | ----------------------- | --------------------------------------------------------------------------------------------------------------- | | [DATA](/data/) | References a data table directly and returns its values. | | [API\_CALL](/api-call/) | Calls an external application with an HTTP POST request to a specified URL and returns the result to the model. | If you have to write the service on the other end of an `API_CALL`, see [Build a service for API\_CALL](/build-an-api-call-service/). ## Choosing between similar functions **DATA vs API\_CALL** * Use `DATA` when the values already exist in your uploaded/source tables and should be consumed directly in the model * Use `API_CALL` when the values must be computed or retrieved externally and returned as a cube ## Pitfalls & troubleshooting * **DATA returns empty:** verify `DataSource`, `Table`, `Measure` names match exactly * **DATA is empty for specific slices:** check whether your model dimensions, levels and level values match the uploaded table values (name/case) * **Units behave unexpectedly:** confirm whether you rely on measure metadata or explicitly set the optional unit parameter in `DATA` * **API\_CALL is unavailable:** it may require enablement (for example a separate subscription or configuration) * **API\_CALL returns an error:** ensure the response follows the expected Valsight table/cube JSON structure and includes the required result shape; otherwise Valsight can’t cast it into a node * **API\_CALL fails due to restrictions:** check configuration limits (for example allowed URLs, payload size/row limits, and timeouts) ## Related * [Function catalog](/function-catalog/): full signatures, parameters, and examples * [Filtering & data shaping](/filtering-data-shaping/): select, fill, pick, rank after loading data * [Dimensionality & hierarchies](/dimensionality-hierarchies/): make the loaded data match required output shape --- # Data & Dimension Validation URL: https://docs.valsight.ai/data-dimension-validation/ Description: Validate that uploaded data is correctly formatted, contains expected values, and complies with your defined dimensions. Validate that uploaded data is **correctly formatted**, contains **expected values**, and complies with your **defined dimensions**. ## How it works The validation function checks uploaded base data against the project's dimension definitions. It verifies that: * Data is correctly formatted * Values fall within expected ranges * Level values match the defined dimensions If deviations are found, the validation tool reports the kind of error and its exact location. ## Steps ### Validating uploaded data 1. Open the **Data Source** page for the file you want to validate. 2. Click **Validate Dimensions**. **Validate Dimensions** opens a results page of its own, listing any issues with their location and type. It shows at most 1000 issues, so on a large data source treat a full page as a sample rather than the complete count. The Data Source page sits in the management area, and you need edit access to the data source to run the check. The button next to it, **Show Usages**, answers a different question: it lists the nodes and project variables that reference this data source, which is the same report described under [Impact check when changing data sources](#impact-check-when-changing-data-sources). ![image-20260402-090717.png](./images/6861651970.png) ### Impact check when changing data sources When you rename or delete a data source, Valsight first checks what depends on it: the nodes that read from it, and the **project variables** that reference it. What happens next depends on the answer. * **If nothing depends on it**, the rename or deletion is carried out straight away. There is no confirmation step. * **If something does**, Valsight shows the impact report first, listing the affected nodes and variables. The action goes ahead only once you confirm it with **Rename** or **Delete**. > **Do not rely on the confirmation as a safety net.** It only appears when the data source is actually in use, so a delete you expected to be able to review can complete immediately. Use **Show Usages** on the Data Source page to see the same report before you start. ![image-20260402-090531.png](./images/6861357073.png) ## FAQ **What does data validation check?** It checks that uploaded data complies with your dimension definitions, is correctly formatted, and contains no unexpected values. **Do I need to validate every time I upload?** It is recommended after any data upload or dimension change to catch issues early. **What happens if validation finds issues?** The validation report lists each issue with its location. You can then fix the problems in your source data and re-upload. ## Related * [Model Validation](/model-validation/): verify model formulas and node compatibility * [Workspace Validation](/workspace-validation/): check workspace scenarios --- # Data Display in Charts and Tables URL: https://docs.valsight.ai/data-display-in-charts-and-tables/ Description: Choose what a chart or table shows and at which level of aggregation, including combining nodes of different dimensionality and adding totals. Valsight works natively with high-dimensional data. A single data point of a **Sales** node can represent one combination of country, month, product and channel ([more on dimensionality](/creating-maintaining-dimensions/)). A chart shows two dimensions at a time, so every chart involves a decision about what to do with the rest. *Tip: if you are new to charts in Valsight, read [Creating Charts](/creating-charts/) first, and [Formatting Charts](/chart-configuration/) once your chart shows the right data.* ## Aggregation is the decision A node holds more dimensions than a chart can display. The axes you set decide two things at once: which dimensions the reader sees, and what happens to the dimensions left over. Anything not placed on an axis or restricted by a filter is aggregated away. How it is aggregated, by sum, average or otherwise, is not a chart setting. It follows the [Aggregation Settings](/aggregation-settings/) configured on the node in the model editor. The dimensions **scenarios**, **years** and **nodes** are special: they should never be aggregated. Each has to sit on an axis or be pinned by a filter. This works the same way for charts, tables, and scenario and time bridges. ## Setting the axes 1. [Create a chart or table](/creating-charts/). 2. Click the **Configure Axes** button. 3. Place the dimension levels you want on rows and columns. Drag a level to move it between the two. 4. Confirm. To swap the two axes wholesale, use the **Switch** button beside **Configure Axes**. It transposes the whole configuration, levels and their subtotal settings together, which is quicker than dragging levels across one at a time. It is unavailable on split slider, tree and KPI charts. Dimension levels that are grayed out are not present in the node you are charting. Scenarios and assumptions are added in the same way as ordinary dimensions. ### A worked example Take monthly clothing store sales in quantity for 2017 to 2019. Besides the time dimension, which runs Year to Quarter to Month, the data carries three dimensions: | Dimension | Level | Level values | | ------------- | -------------- | -------------------------- | | **FLocation** | FCountry | CH, DE, AT, Other | | **FProduct** | FProduct-Group | Clothes, Accessories | | **FProduct** | FProduct | T-Shirt, Pants, Sunglasses | | **FChannel** | FChannel | Offline, Online | To see aggregate results for the business as a whole, put country, product group and quarter on the axes and leave channel off. Channel is then aggregated away, and the chart shows quarterly figures per country and product group. ## Totals There are three ways to add a total, and the difference between them is how they treat filtered-out data. | Total | Where | What it aggregates | | ------------------------------- | --------------------------------- | --------------------------------------------------------------------- | | **Grand totals** | **Configure** menu | The visible data | | **Subtotals** | **Configure** menu | The visible data | | **Show values of higher level** | Checkbox below the totals options | All data belonging to the higher level, including filtered-out values | Two restrictions apply. Subtotals and the higher-level value cannot be shown at the same time. And a **grand total cannot be calculated over an axis carrying nodes or scenarios**: ask for one and the Configure Axes dialog warns that ‘Grand totals cannot be calculated across nodes or scenarios.’ This catches the case described below, where the nodes option is put on an axis. ![The Configure menu with the grand totals option](./images/5202706439.png)![The Configure menu with the subtotals option](./images/5202739237.png) ### Totals over visible data Grand totals and subtotals aggregate what the reader can see. Filter a value out and the total drops accordingly. The original table: ![A table of vehicle models grouped by vehicle class, with no totals](./images/5202903056.png) With subtotals activated per column: ![The same table with a subtotal row under each vehicle class](./images/5202804747.png) With **Grand SUV X** and **Fancy Sedan 1** filtered out, the subtotals now aggregate only the rows still shown: ![The same table with two models filtered out and the subtotals reduced to match](./images/5203001348.png) ### Totals over all data Including a higher level of a dimension gives you the total of that level regardless of the filters, because it aggregates everything belonging to it. Adding quarters to a monthly chart is the usual case: you can filter down to a few months and still read the full quarter total beside them. Here **Show values of higher level** is switched on. It is available because **Model** and **Vehicle Class** are levels of the same dimension: ![The same table with SUV Total and Sedan Total showing the full totals including the filtered-out models](./images/5202968584.png) The SUV and Sedan totals now cover the visible and the filtered-out rows together, which is what you want when comparing a single level value against the total of its level. > **Note:** > > Subtotals and the unfiltered value of the higher level cannot be shown at the same time. ## Combining nodes of different dimensionality A single chart or table can show several nodes, even when they do not share the same dimensions. 1. In the **Configure Axes** dialog, add the **nodes** option to an axis. 2. Add the nodes you want through the tile settings. 3. For any dimension that is not present in all of the selected nodes, also include that dimension's **(total)** level. Step 3 is what makes the mismatch work. Without it, a node that lacks the dimension has nothing to display against it. **Configuration:** ![The Configure Axes dialog with nodes added to an axis](./images/5094215146.png) **Result:** ![A table showing inflation and sales as two nodes side by side](./images/5094214848.png) To show sales at product level while keeping the inflation numbers, which have no product dimension, include both **FProduct (Total)** and **FProduct** in the table. ## Good to know * **Aggregation is set on the node, not the chart.** Whether a dimension sums or averages comes from the node's [Aggregation Settings](/aggregation-settings/). Changing the axes changes what is aggregated, never how. * **A grayed-out level means the node does not have it.** It is not a permissions problem. * **Subtotals and higher-level values answer different questions.** Use subtotals for "what do the rows I am looking at add up to", and a higher level for "what is the real total, including what I filtered out". * **A node missing a dimension needs that dimension's (total) level.** Otherwise it drops out of the chart when the dimension goes on an axis. * **A table with nodes in rows unlocks extra options.** It carries additional formatting settings and can build an automatic hierarchy. See [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/). * **Assumptions on an axis add two checkboxes.** Putting assumptions on rows or columns offers creating YoY bridges and showing assumption details. See [Time Bridges](/time-bridges/). ## Related * [Creating Charts](/creating-charts/): adding a chart and pointing it at your data. * [Formatting Charts](/chart-configuration/): sorting, scales, colors and table styles, once the data is right. * [Aggregation Settings](/aggregation-settings/): how a node aggregates, set in the model editor. * [Table Formatting](/table-formatting/): table style, column widths and merged header cells. --- # Data Effects Display in Bridge URL: https://docs.valsight.ai/data-effects-display-in-bridge/ Description: Split the model's own contribution to a time bridge out per node, or group several nodes into one named block. If you look at a bridge that analyzes differences from one year to the other, you will see the base values for both years and a number of smaller steps that lead from one base to the other. These differences come from two different sources: * **Data effects**: the model's own contribution, from base data that changed between the two periods * **Assumption effects**: the simulation's contribution, from the assumptions and line-items active in the scenario Differences in the model are, in most cases, circumstances that you cannot influence (like fixed costs); by default, they are displayed in one large block. If you want to split them up per node or group them together, you can mark the respective nodes in the model and activate the setting in the chart. ## Goal Break the model's own contribution to a time bridge out of its single block, either into one effect per node or into named groups of nodes such as a combined "price effect". ## Prerequisites * A [time bridge](/time-bridges/) on your worksheet. Choose one scenario and two years, quarters or months, then select **Bridge between periods (e.g. YoY)**. * Edit rights on the model the nodes live in, since part of the setup happens in the model editor. ![The bridge between periods option when creating the chart](./images/5147689010.png)![The resulting time bridge with one block for data effects](./images/5094212319.png) ## Steps ### Show data effects per node 1. Open the model the node lives in. 2. Select the node and switch on **Show data effect in bridges**. ![The Show data effect in bridges setting on a node](./images/5094212411.png) 3. Go back to the workspace, select your bridge, and set **Data effects** in **Bridge Settings** to **Detailed**. ![The Data effects setting in the bridge settings of the chart editor](./images/5148344359.png)![The bridge with one effect per node, each labeled with its node and model name](./images/5094212491.png) The bridge now shows a separate effect per node, each labeled with the node's name followed by its model's name in parentheses, for example **Fixed Costs (Cost Model)**. ### Group several nodes into one effect 1. In the model editor, fill in the **Group Key** field on each node you want combined. Nodes sharing a group key become one block in the bridge, which is how you build something like a single "price effect" out of several nodes. 2. Set **Data effects** in **Bridge Settings** to **Grouped**. ![The bridge with data effects combined into named groups](./images/5094212462.png) The group key is also the name shown in the chart, so it doubles as the label. ## Verify Your bridge's data effects are no longer a single block: * With **Detailed**, one step per marked node, labeled with the node name followed by its model's name in parentheses. * With **Grouped**, one step per group key, labeled with that key. A node that has **Show data effect in bridges** on but no group key is not folded into anything: it keeps a step of its own, labeled with its node and model name exactly as in **Detailed**. If the block is still whole, check that **Show data effect in bridges** is switched on for the nodes and that **Data effects** is not still on **Total**, which is its default. ## Related * [Time Bridges](/time-bridges/): creating the bridge in the first place, and how the effects are calculated. * [Assumption Effects](/assumption-effects/): how the simulation side of a bridge is derived. * [Grouping Assumption Effects](/grouping-assumption-effects-in-bridges/): the equivalent grouping for assumption effects. --- # Data Import & Export URL: https://docs.valsight.ai/data-import-export/ Description: Data in Valsight provides the input values that feed models and serve as the baseline for calculations, simulations, and analysis. **Data** in Valsight provides the **input values that feed models** and serve as the baseline for calculations, simulations, and analysis. ![image-20260415-194716.png](./images/7009107972.png) --- # Data Permissions URL: https://docs.valsight.ai/data-permissions/ Description: Data permissions define which data a user can access. They can be configured for a project and will be enforced in workspaces. Data permissions define which data a user can access. They can be configured for a project and will be enforced in workspaces. ## Configuring data permissions Data permissions are based on a function called *data permission classes*. Data permission classes create a link between [users/groups](/manage-users-and-groups/) and dimension values, enforcing that the user has the right to see data for the respective dimension value. [Users/groups](/manage-users-and-groups/) can be given access to a data permission class and will then be able to see the respective data in charts. ### Defining a security concept As a first step, you should define your security concept and decide which dimensions you want to use to control data access. Although multiple dimensions can be used at once, it is advisable to choose one dimension for the access restrictions. If you have chosen the dimension, think about how fine granular you want to differentiate the access rights inside this dimension. As an example, think about an entity dimension with the organizational structure. You could decide that all segments in one business unit are always bundled together, and access is assigned to this bundle. In contrast, you could have the requirement to differentiate access rights individually for each segment. ![Artboard.png](./images/5094191628.png) **Example:** Assume the following example with a dimension “*Location”* with countries and citiesthat should be used to define data permissions. The goal is to differentiate two groups of users: (1) city managers that are allowed to drill down to the individual cities and (2) country managers that are only allowed to see the totals of the countries. The two data permission classes #*Countries* and #Cities in combination with the groups for country and city manager reflect this structure and allow us to easily assign new users to one of the groups. ### Create data permission classes The next step is creating the actual data permission classes. 1. Navigate to the configuration menu, open your project and choose “*Security”.* ![image-20231116-133846.png](./images/5286494209.png) 2. Here you will see the section “*Data Permissions”* and the “*Manage”* button will allow you to create and manage the data permission classes. ![image-20231116-134516.png](./images/5286756353.png) 3. Create one class per bundle of values that you want to be able to differentiate and name accordingly. **Example:** To create the structure described above, we create two new data permission classes: *#Countries* and *#Cities.* ### Assign dimension values When you have the data permission classes created, you can assign them to values in dimensions. 1. Open “*Assign Values”* from the data permission section on the project's “*Security* settings” page. You will see a list of all your dimensions within the project. 2. A selected dimension will be listed with all its values, and you can select a data permission class for each value. Assigning a data permission class means that any user who wants to display data in a chart will require access to this dimension’s values. By default, all values are set to a default value that can be changed at the very top of the page. The data permission classes “*ALLOW”* and “*DENY”* are system generated and will either grant all users access to the level or deny access for all users. *“ALLOW”* is the default selection. You can assign data permission classes to any aggregation level, so it is possible to allow users to see data on an aggregated level but prohibit a drill down to lower levels. **Example:** Following the example from above, we assign the data permission class *#Countries* to all countries (e.g. Germany) and #Cities to all cities (e.g. Berlin, Munich). ![Screen Shot 2018-05-08 at 14.37.18.png](./images/5094191643.png) ### Configure access rights The last and final step is to grant [users or groups](/manage-users-and-groups/) access to your configured data permission classes. As a **best practice**, try to give **groups access to data permission classes** and **assign users to groups**. Hereby, users will be granted access due to their group membership and stay better manageable. To give users and groups access to a data permission class, open the “*Configure”* button on the project's “*Security* settings” page. The resulting page shows all data permission classes in the columns of the matrix and groups or users in the rows. To edit the access rights for a data permission class, press the “*edit”* button in the header row and add the respective users or groups to the read or write access lists. * **Read access** will allow users to view data associated with this data permissions class as part of charts and analyses in workspaces. * **Write access** will allow users to create and change assumptions containing data associated with this data permission class. **Example:** [Create the two groups](/manage-users-and-groups/) *City Managers* and *Country Managers.* Configure the access rights for the as shown below, so that the city managers have access to #Cities and the country managers to #Countries. ![Screen Shot 2018-05-08 at 14.42.25.png](./images/5094192867.png) ## Exceptions where permissions are not enforced Data permissions are only enforced in workspaces and models. They will not be enforced in: * **Data Source Management:** Data permission classes are not enforced on the data sources in the data source management. Users with access to these data sources can see the complete data. (e.g. users with “Edit” access to models can see the underlying data sources of a model. * **Presentations:** When viewing a presentation, users with access to a presentation will be able to see the full data that is contained in this presentation, independent of their data permissions. This also means, that if a user with insufficient permissions created a presentation, any other user will see the same permission error in the presentation independent of his data permissions. * **Project Admins:** Data permission classes are not enforced on project admins > When a level, that is included in a data permission class, is not on a node that is the base of the chart, everyone can see the data in the chart. ## Exporting projects with data permissions When exporting a project, its data permission classes will be exported as well. However, as users are not part of a project they will not be contained in the project export. This means that the access rights for users to data permission classes have to be set again manually after importing a project. --- # Data Preview of Nodes URL: https://docs.valsight.ai/data-preview-of-nodes/ Description: The data preview is part of the operations/formula editor in a model. The data preview is part of the operations/formula editor in a model, and gives you a first overview of a node's data. You as a user are able to check the displayed data before for example continuing to work on your model. Furthermore, the data preview allows continuous cross-checks to validate the effects of functions and calculations. ![image-20231025-145217.png](./images/5263720515.png) ## Functionalities ### Default scenario Setting a scenario as a default scenario enables a standardized view onto your data while switching between data previews of multiple nodes. It can be a baseline or a simulation run. Use the two buttons next to the scenario selector: * **Save as default** stores the current selection. It is disabled once that selection is already the default, with the tooltip "Already your default". * **Clear default** appears only when a default is saved. It resets the preview to the baseline the Model Editor passed in, and is disabled when that is already the state, with the tooltip "Already using model default". The default scenario is saved per user *and* per project, so each project can have its own. ### Level filter You can set individual filters for every available level in this table. By opening the dropdown menu of a level on either of the axes, the user is able to filter out the available level values. ### Buttons The toolbar groups these buttons under **Levels**, **Filters** and **View**. | Button | Group | What it does | | -------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Remove all** | Levels | Takes every level off both axes, leaving an aggregated view of the data based on the selected [aggregation type](/aggregation-settings/) which can be set in the upper left corner of the table. Level filters are kept, so the total covers the still-filtered subset. | | **Add all** | Levels | Puts every available level back on its axis (time in columns, all others in rows), for the most detailed data preview. Level filters are kept. | | **Clear** | Filters | Removes all set level filters. This is the only button that touches filters. | | **Save** | View | Saves all current data preview configurations (levels on axes, level filters,...). These configurations are not only saved for the data preview of this one Node, but for all Models of a Project. This enables you as a user to apply the same filters to multiple Nodes when for example doing drill-downs. | | **Restore** | View | Restores the last saved data preview configurations and applies them in the selected data preview. This can not only be done in the same data preview, the configurations have been saved in, but in every data preview of the same Project with at least one equal level. In case of Nodes having only 2 overlapping levels, saved configurations only apply to those 2 overlapping levels. | ### Additional instance setting for data preview An instance administrator can set a cell limit for the data preview. In case a data preview exceeds this cell maximum, the data is automatically aggregated to a summed-up total. That allows a cleaned-up and improved data overview. The setting can be found under the Valsight settings > Settings under the heading 'Calculations'. It is called `featureFlags.DataPreviewShowsSumsByDefault`, and the default maximum cell number is 100,000. This is an instance-wide setting, not a per-project one: it is set once and applies to every project on the instance. ## Example To simplify the effect of each button, they will be explained based on an example. For the following example, an imaginary automobile project is used. The time horizon is 2019-2030. The model contains the following levels and level values:

Level

Level value

Vehicle Class

SUV

Sedan

Model

Fast SUV Y

Grand SUV X

FamilyFirst Sedan 2

Fancy Sedan 1

Engine

BEV

ICE

PHEV

The context of the example is that the data preview shows the price per car, based on their vehicle class, their model, and their engine over the time horizon. There is no increase in prices over that horizon. ### Starting point The starting point for the example is the initial data preview, without any filters or aggregations. ![image2021-9-8\_15-34-5.png](./images/5094218818.png) ### Remove all The 'Remove all' function aggregates the data, to summed-up totals and reduces the data overview to a minimum amount of data for a better overview. In this example, the data preview is aggregated to the total costs over the time horizon for both vehicle classes. This function clears the axis configuration. Any level filters you have set stay in place, so the totals cover the filtered subset rather than the whole node. ![Clear All .gif](./images/5094218833.gif) ### Add all The 'Add all' function applies all available levels to the according axes. Level filters are left alone. In this example, levels have been reconfigured/shifted on the axes. Via the 'Add all' function these configurations are reset and the available levels are applied to their respective axes. After using the 'Remove all' function, 'Add all' applies all available levels back to their axes. To clear filters as well, use 'Clear' in the Filters group. ![Apply All.gif](./images/5094218838.gif) ### Clear For the 'Clear' function, the filters have been set on 'Years' (show 2019, 2020) and 'Engine' (show BEV). With 'Clear', those filters are reset back to show all available level values. ![Clear All filters.gif](./images/5094218828.gif) ### Save and restore The 'Save' and 'Restore' functions work hand in hand. In the following example, level filters have been set on the vehicle class (show SUV), the Engine (show BEV), and the Year (show 2021 - 2024). These configurations have been saved. After continuing to work on the data preview with several filters, the previously saved configurations have been restored via the 'Restore' - button. This restoring can not only be done in the same data preview, but for the data preview of all Nodes of the Project. > The 'Save' and 'Restore' functions are user bound. That allows user A to save and restore different data configurations than user B. ![Save and restore.gif](./images/5094215245.gif) --- # Data Source Upload URL: https://docs.valsight.ai/data-source-upload/ Description: Learn how to structure your data in the excel file so that it can be used in Valsight. Learn how to structure your data in the excel file so that it can be used in Valsight. Go to the data management section in Valsight by clicking on the grid icon on the left. Create a data source with the **New Datasource** button above the list and choose **XLSX** from its dropdown. To swap the file of an existing data source, open it and use the **Replace Data Source** section at the bottom: pick the new file and click **Update Data Source**. The replacement removes the previous file. Each excel sheet is loaded into an internal database table. Every data node or DATA function references exactly one excel sheet. Sheets that start with a number sign (#) are ignored, and so are worksheets that are hidden in Excel: visibility is checked before the number-sign rule, so hiding a sheet silently removes its table from the upload and can trip the ‘Table is still in use’ error if the model references it. The first line of each sheet is interpreted as the header row and determines the column names of the resulting internal table. The same number-sign convention works per column: a column whose header starts with (#), or is empty, is ignored, which is how helper and comment columns are kept out of the table. Valsight recognizes the formatting options of the cells in Excel, hence all structural information (labels, text, levels, level values) have to be formatted as "General" or "Text". On the other hand, all measures have to be formatted as "Number". ## Data structure - best practices We recommend to split your data into two excel files, one to define dimensions and another one to upload data. You may create more than one data sheet, e.g. if there are different data sources, or very large data sheets that take long to load. When formatting your Excel sheets adhere to the [Naming Guidelines](/naming-guidelines/) for best results. Excel files are always uploaded in the data management section, which is linked from the "grid icon" in the left menu. ## Create hierarchies & dimensions See [Dimension & Hierarchy Management](/dimensions/) for more information how to create hierarchies & dimensions. ## Upload data & formatting data in your Excel sheets | **Recommended:** create standard upload tables | **Advanced:** create a 2D/3D data table | | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | | Normal upload tables, flexible number of levels, easy to understand. | Useful in situations where your data comes pre-formatted from legacy systems. | | See [Create Upload Tables](/create-upload-tables/) | See [Multidimensional Data Upload (2D/3D/4D Tables)](/multidimensional-data-upload-2d-3d-4d-tables/) | Find examples at the [Example Excel Sheets](/example-excel-sheets/). ## Further information ### Limitations [Limitations & Data Sizing Guidelines](/limitations-data-sizing-guidelines/) ### Recognized column names Valsight links a column to a level whose name matches its header, plus a fixed set of aliases for measures, time levels and Sequence. See [Recognized Column Names](/recognized-column-names/). ### Create one Excel sheet for multiple data nodes [Create one Excel Sheet for Multiple Data Nodes](/create-one-excel-sheet-for-multiple-data-nodes/) (This upload method is not recommended for new models.) ### Integration scenarios Of course, later on the integration of ERP Software is possible - get in contact with the Valsight Support team to evaluate your integration scenarios. --- # Data Upload Errors, Warnings and Infos Explained URL: https://docs.valsight.ai/data-upload-errors-warnings-and-infos-explained/ Description: On this page you'll find the meaning of the different Error, Warning and Info Messages when Uploading Data to Valsight. On this page you'll find the meaning of the different Error, Warning and Info Messages when [Uploading Data to Valsight](#). ## Overview The table below summarizes each upload message and its severity. | Message | Severity | | ---------------------------------------------------------- | :---------------------------------: | | [Table is still in use](#table-is-still-in-use-errorpng) | ![Error](./images/5094207687.png) | | [Duplicate table](#duplicate-table-errorpng) | ![Error](./images/5094207687.png) | | [Empty table](#empty-table-warnpng) | ![Warning](./images/5094215064.png) | | [Column is still in use](#column-is-still-in-use-errorpng) | ![Error](./images/5094207687.png) | | [Duplicate Column](#duplicate-column-errorpng) | ![Error](./images/5094207687.png) | | [Wrong parent or child](#wrong-parent-or-child-errorpng) | ![Error](./images/5094207687.png) | | [Conflicting links](#conflicting-links-errorpng) | ![Error](./images/5094207687.png) | | [Invalid value](#invalid-value-errorpng) | ![Error](./images/5094207687.png) | | [Empty measure](#empty-measure-errorpng) | ![Error](./images/5094207687.png) | | [Non-numeric measure](#non-numeric-measure-errorpng) | ![Error](./images/5094207687.png) | | [Duplicate Row](#duplicate-row-warnpng) | ![Warning](./images/5094215064.png) | | [Added Rows](#added-rows-infopng) | ![Info](./images/5094218965.png) | | [Deleted Rows](#deleted-rows-infopng) | ![Info](./images/5094218965.png) | | [Changed Values](#changed-values-infopng) | ![Info](./images/5094218965.png) | Whether a message stops the upload is a per-project setting. **Error** blocks the upload; **Warning** and **Info** let it go through. An administrator can change the severity of each message with the project setting `featureFlags.uploadDataSeverityValues`, and any message that is not listed there is treated as an error. ### **Table is still in use** Error.png This error appears when a newly uploaded Excel document does not contain worksheets that are currently being referenced in our model. To resolve this you can either add the required worksheets to the new Excel document or remove the reference to the old worksheets inside of the model. To identify where a table is used, navigate to the Valsight settings > Projects > choose the Project > Show Data Sources > Usage report (> Details). **Example:** Our current document 'Base data.xlsx' contains the following worksheets: ![Base Data sheets.png](./images/5094207400.png) All of these worksheets are being referenced in multiple places inside our model. For example in the base data submodel. ![reference base data in model v2.15.png](./images/5094207636.png) Our new data source only contains the following Worksheets: ![DemoContent4 sheets.png](./images/5094207424.png) If we try to upload this document the [data upload wizard](#) will show the error ‘table is still in use’. To fix this we can either copy the worksheets from the old into the new Excel document or remove all references to the old worksheets inside our model. ![table still in use error v2.15.png](./images/5094207532.png) Make sure to also add the contents of a worksheet when you are adding missing worksheets to your new Excel document. Otherwise, the error will persist. ### **Duplicate table** Error.png There is more than one sheet (Excel) or table (database) with the same name. To resolve this rename the sheets or tables in question and reupload the file or reimport the database again. ### **Empty table** [Warn.png](#duplicate-row-warnpng) A sheet (Excel) or table (database) has column headers but is otherwise empty. Delete it from the document or add rows to resolve this error. ### **Column is still in use** Error.png Similar to “[Table is still in use](#)”, this error appears when a column that is referenced inside the model isn't part of the new Excel document. To resolve this you can either add the required columns to the new Excel document or remove the reference to the old columns inside of the model. **Example:** Our new file does not contain the column 'Volume' which is referenced in our submodel. ![base data missing volume with worksheets cropped.png](./images/5094204495.png) ![reference base data in model v2.15.png](./images/5094207636.png) If we try to upload it the error 'column still in use' will appear. To resolve it, we can either add 'Volume' back to our file or remove the reference from the submodel. ![column still in use error v2.15.png](./images/5094204476.png) ### **Duplicate column** Error.png You will receive this error if your Excel document contains a column two or more times. Remove the redundant columns to fix the error. **Example:** Our new data source contains the column "Billed Days" twice. ![excel duplicate column.png](./images/5094211531.png) When we try to upload said data source, we'll receive the error "Duplicate column". The data upload wizard also shows which sheet and column are affected. Just delete the highlighted, redundant column and you are good to go. ![duplicate column v2.15.png](./images/5094211498.png) ### **Wrong parent or child** Error.png This error appears when the hierarchy of a level (Paris) and its parent (Germany) is not the same as specified in the dimension management. In this example, the parent of Paris is France and not Germany. ![image2020-11-2\_14-28-10.png](./images/5094191164.png) Try to sort out if you have to change your excel file or database to match with the dimension management or vice versa. ![image2020-11-2\_14-27-57.png](./images/5094191179.png) ### **Conflicting links** Error.png Similar to [Wrong parent or child](#), this error appears if the linked attributes that are used in the excel file or database are not the same as in the dimension management. In the example below, "Auto2" has a linked Color "Blau" in the excel file, but "Rot is linked in the dimension management. ![image2020-11-2\_14-34-25.png](./images/5094191174.png) vs ![image2020-11-2\_14-34-42.png](./images/5094191159.png) ### **Invalid value** Error.png This error appears when the dimensions or level values in Valsight don't match with the ones in the uploaded Excel document. Edit the [dimension and hierarchy management](#) to match your base data to fix the issue. **Example:** The Excel document containing our base data is referencing the level value 'Service 3' in lines 7 and 13. ![Service 3 in Excel.png](./images/5094207616.png) When we try to upload our base data we get the error 'Invalid Value'. The [data upload wizard](#) also shows us which values are affected. Here we can see that lines 7 and 13 in the column 'Product' are affected. ![Invalid values v2.15 service3.png](./images/5094207548.png) If we check inside the [dimension management](#) we'll see that the level value 'Service 3' is missing. Once we add the value the upload will work as intended. ![Dimensions missiong service 3 v2.15.png](./images/5094207590.png) 'Invalid values' also appear, when whole dimensions or hierarchies are missing. In addition to that, it appears when hierarchies aren't set up correctly (e.g. 'ProductGroup' containing the values for Products and vice versa). ### **Empty measure** Error.png This error appears if a column that Valsight reads as a number contains a cell without a value in it. Empty cells in level or dimension columns do not raise it. Fill in the missing values in the measure columns to fix the error. **Example:** Our Excel document is missing two values in the columns "TotalRevenue" and "BilledDays". ![Excel Empty Cell.png](./images/5094215046.png) Once we upload the file we receive the error "Empty measure" along with the position it is in. Fill in the missing values to resolve the error. ![Empty Cell v2.15.png](./images/5094215217.png) ### **Non-numeric measure** Error.png This error appears if a column that Valsight reads as a number contains a value that is not a number, for example a text or a stray character. It is the sibling of *Empty measure* and comes from the same check, but it is not part of the default severity list, so it blocks the upload unless an administrator lowers its severity. Correct the offending cells, or make the column a level column if it is not meant to hold numbers. ### Duplicate row Warn.png This warning appears if the same combination of dimension and level values occurs in more than one row. Only the level columns are compared, so two rows can be reported as duplicates even when their measure values differ. Check the affected rows before discarding any. **Example:** Our Excel file contains the last row twice. ![Duplicate Row Excel.png](./images/5094215177.png) When we upload the file we'll get the warning "Duplicate Rows" as well as the information on which rows are the duplicated ones. ![Duplicate Row v2.15.png](./images/5094215160.png) Even though you can still upload an Excel file with duplicate rows, we advise against it since it might lead to unintended consequences while building your model. ### **Added rows** Info.png This message appears if new rows were added to your data source. It also shows you, which rows were added specifically. **Example:** We added a new row (row 5) to our Excel file. ![excel added rows.png](./images/5094218618.png) Once we upload our new file the data upload wizard will show us which rows were added. ![added rows v2.15.png](./images/5094218589.png) ### **Deleted rows** Info.png This message appears if rows were deleted from your data source. It also shows you, which rows were deleted specifically. **Example:** We now deleted the previously added row 5 from our Excel file. ![Excel deleted rows.png](./images/5094218658.png) Once we upload the file the data upload wizard will show us which rows were deleted. ![deleted rows v2.15.png](./images/5094218853.png) ### **Changed values** Info.png This message appears when values in your newly uploaded Excel file change compared to the existing data source. It also shows you which values have changed specifically. **Example:** We changed the values in rows 27, 28, and 29 of our Excel file. ![excel changed values.png](./images/5094215471.png) Once we upload the file, the data upload wizard will show us which rows were modified. ![changed values v2.15.png](./images/5094215458.png) --- # Data Upload & Import/Export Overview URL: https://docs.valsight.ai/data-upload-import-export-overview/ Description: Learn why and where to import and export files to and from Valsight, and find out which data formats are supported. Learn why and where to import and export files to and from Valsight, and find out which data formats are supported. ## Basic overview * Data can be imported and exported at several places in Valsight * Importing data enables a quick and easy setup of base data, drivers, assumptions, and more * Exporting data from Valsight allows you to save software-generated data, charts, and configurations for further usage * Valsight supports a multitude of data formats and interfaces (e.g. XLSX, OData, CSV, JDBC) ## Importing and exporting data Uploading external data allows you to quickly build [models](/models/), simulations, and visualizations based on pre-existing databases. That way, you do not have to manually insert your relevant data, but can save time and enable a seamless connection between your business's databases and Valsight. In the same manner, calculated or otherwise generated data can be exported to extract data sets, integrate processed data back into other databases, or simply to save the configuration settings of Valsight functions. Exporting data from Valsight and creating charts with other programs can be a complicated effort. To simplify this process, exported Valsight data can be linked directly to a PowerPoint or Word file. ## Valsight instances that support the import/export of files When using Valsight, there are several instances that support the up- or download of data. These instances are: * Projects * Data Source Space * Dimension Management * Model Editor * Workspaces * Scenarios * Assumptions * Line-Items * Charts * Presentations ![Abbildung\_Importing and Exporting Data from Valsight\_26\_10\_2023.png](./images/5264310284.png)![Abbildung\_Importing Exporting Data to Valsight\_26\_10\_2023.png](./images/5264474155.png)![image-20230622-120733.png](./images/5166071845.png) ### Projects It is possible to im- and export entire projects. To do so, head to the configuration menu by clicking the cogwheel on the navigation bar. ![Heading to Admin UI.png](./images/5094231024.png) From there, select “Projects” to open the project settings. Select the project you want to export and click “Export” to download the project as a ZIP file. ![Export Project.png](./images/5094216923.png) Here you can also import a project by uploading it as a ZIP file. ![Import Project.png](./images/5094216910.png) ### Data source space The data source space is fundamental to Valsight. Here you can [upload your main data sources](/create-and-update-data-sources-step-by-step/) to base your driver model on. Upload a structured file and Valsight will allow you to access the data in a comprehensive way by structuring it with your [base model](/models/). Information on how to correctly structure data so that Valsight can utilize them [can be found here](/restructuring-data-in-excel-using-power-query/). You can also download the base data of a project that has previously been uploaded, making it possible to upload an adjusted version of an existing database. The supported base data format is **XLSX,** with **OData, and JDBC** connections also being supported, allowing manual as well as automated uploading of base data. For further information on external data sources like OData and JDBC, please take a look at [our dedicated guide](/external-data-source-connections-odata-jdbc/). An in-depth guide on how to create and update data sources in Valsight [can be found here.](/create-and-update-data-sources-step-by-step/) ![Upload Data Source Space.png](./images/5094211095.png) ### Dimension management The [dimension management](/creating-maintaining-dimensions/) supports the creation of dimensions based on imported **XLSX** files. This way you only have to manually insert dimension hierarchies, but do not need to insert level values. You can also download an **XLSX** file of an existing dimension if you wish to implement minor changes to the existing dimensions. ![Upload Dimension Manager.png](./images/5094211084.png) ### Workspaces [Workspaces](/workspaces/) can be exported as either raw or formatted **XLSX** files, allowing a quick extraction of generated data. Raw XLSX files are easier to transform and display data in a more machine-friendly way but may be hard to read for human users. The raw XLSX exports a file that contains raw data structures (primary data) that have not yet been processed for use. Raw data is organized in columns and rows without merged cells. Each column represents one single data category, and every row contains data for each column. Formatted XLSX files are easier to comprehend but might be incompatible with other software or databases. The formatted XLSX option exports a file that is structured in tables with sorted data and additional information (for example applied Filters). A formatted export also includes merged cells. This option might be used in the case of presenting data to others via excel. ![Export Worksheet.png](./images/5094231072.png) #### Charts Charts can be exported as XLSX or OData. As XLSX you can export the raw and formatted data of individual [charts and tables](/data-display-in-charts-and-tables/), giving you a more specific option for exporting simulation data. The OData link will automatically be copied to your clipboard. ![image-20230622-122533.png](./images/5166530600.png) ##### Chart export formats: what data to expect When exporting a chart, the three data formats (Formatted XLSX, Raw XLSX, and OData) differ not only in layout and file type, but also in which data they include. Understanding these differences is important when using exports for downstream processing or reporting. A fourth option, **Image (PNG)**, exports the picture rather than the data and is covered at the end of this section. ###### Formatted XLSX The formatted export mirrors what is displayed in the chart as closely as possible: * Data is structured in a human-readable table with merged cells, applied filters, and groupings. * Totals and subtotals are included where they appear on the chart. * Data series hidden via the [Hide checkbox](/configure-flexible-scenario-comparisons-in-a-single-chart/) in the Style Data Series dialog are **excluded** from the export, consistent with what is visible on screen. * Best suited for presenting data to stakeholders or for use in reports. ###### Raw XLSX The raw export is designed for machine readability and downstream data processing: * Data is output as a flat table: one row per data point, one column per dimension or measure, no merged cells. * Only the **lowest available granularity** is exported. Totals and subtotals are never included in raw exports, regardless of how the chart is configured. * Data series hidden via the [Hide checkbox](/configure-flexible-scenario-comparisons-in-a-single-chart/) in the Style Data Series dialog are **ignored**. All series are exported, including hidden ones. * Best suited for importing into BI tools, databases, or custom processing pipelines. ###### OData The OData export delivers data via a live link rather than a downloaded file. Its data content follows the same rules as the Raw XLSX export: * Only the lowest available granularity is returned. Totals are never included. * Data series hidden via the [Hide checkbox](/configure-flexible-scenario-comparisons-in-a-single-chart/) in the Style Data Series dialog are ignored. All series are returned, including hidden ones. * The link reflects the current state of the chart’s data and updates automatically. * Best suited for live connections from Excel, Power BI, or other tools that support OData feeds. ###### Image (PNG) ‘Export as… → **Image (PNG)**’ saves the chart as a picture rather than as data, so none of the rules above apply to it. It is offered only for charts drawn as graphs (area, bar, column, line, mixed, packed bubble, pie and waterfall). Tables, tree charts, line-item charts and the other tile types have no image to export and do not show the option. ###### Summary | | Formatted XLSX | Raw XLSX | OData | | -------------------------------- | ---------------------------------- | ----------------------------- | ----------------------------- | | Includes totals / subtotals | ✅ Yes | ❌ No, lowest granularity only | ❌ No, lowest granularity only | | Respects hidden data series | ✅ Yes, mirrors the chart display | ❌ No, all series exported | ❌ No, all series returned | | Human-readable layout | ✅ Yes (merged cells, grouped rows) | ❌ Flat table | ❌ Flat / structured for tools | | Machine-readable / tool-friendly | ❌ Not ideal | ✅ Yes | ✅ Yes | | Delivery | File download | File download | Live link (auto-updating) | > **Note:** > > If you have configured a chart to show certain scenarios as totals by hiding cross-product data series using the [Hide checkbox](/configure-flexible-scenario-comparisons-in-a-single-chart/) in the Style Data Series dialog (e.g., hiding “Scenario A – Segment” level values to display only “Scenario A – Total”), be aware that **Raw XLSX and OData exports will not reflect this.** They will always export all data series at the lowest granularity. If you need an export that matches exactly what is shown on the chart, use the **Formatted XLSX** export instead. ### Model Editor The model editor opens another option to upload data. Here you can download existing data sources and apply changes, which can then be uploaded again to your [model.](/models/) Data downloads can also be done with individual nodes, for a clear overview of the processed data. Via the model editor, you can also upload new data sources to create entirely new databases, if the need should arise. The model editor itself supports the upload and download of **XLSX** files. ![Upload Model Editor.png](./images/5094211200.png)![image2021-12-10\_10-15-14.png](./images/5094211434.png) When uploading data via the model editor, Valsight enforces strict conditions in order for the upload to work. This is done to ensure that the newly uploaded data conform with any existing data sources or models. These strict validation checks: * if every level has all and only values for the correct levels * if the parent-child relations are correct, when there are multiple levels in the same dimension * if links in levels of tables/sheets are working properly (when using an XLSX file that is linked to an external source per interface) * if a column that would be deleted by the upload is still used * if duplicate tables would result in multiple tables/sheets with the same name * if duplicate columns exist * for conformity with multiple dimensionality rules * this includes verifying that no multiple data points with the same dimension and level values exist * if there are any empty sheets * if number columns only have numbers * if a sheet that would be deleted by the upload is still used * if number columns contain empty cells * which rows the upload adds, deletes or changes compared with the data source already in the system Note that the bottom right of the dialog contains the “Create new datasource” button. By clicking it, you will be redirected to the data source space, where you can create entirely new data sources instead of just adjusting existing ones. #### Node lists Another export option exists in the download of a list of all nodes belonging to a model. Any admin can do so by heading to the “Configuration” page via the cogwheel on the navigation bar and clicking on “Projects” ![Heading to Project Admin UI.png](./images/5094216318.png) From there, select the project you want to export the node list of and click “Show models”. ![Viewing Models of a Project.png](./images/5094216298.png) Under the header “Nodes:” you can then see the number of nodes related to the model you select from the overview list on the left. By clicking “(see list)” you can view a detailed list of all nodes. You can use filters in the header bar to filter for specific kinds of nodes or search them directly using the search function in the top right corner. By clicking “Download as XLSX” you can download a list of all nodes. You can also manually select specific nodes that should be included in the download; all unselected nodes will not be downloaded if you do so. ![Exporting Node List.png](./images/5094230932.png) #### Exporting a model as DOT file DOT is a simple but powerful language for the description and depiction of graphs and structures. Valsight enables you to download a DOT file of a model, making it possible to depict the nodes and their structure with other software. To export a DOT file of a model, follow the steps in “[Node Lists](#node-lists)” until you get to the model overview in the admin UI. Select the model you want to export as a DOT file and scroll to the bottom of its configurations. ![DOT export.png](./images/5094230984.png) There you can select, which additional information to include in the export. You can also apply a regular expression to filter with or use a rollup. When you’re finished with the configuration, click on “Download Graphviz/DOT File” to download the file. #### Exporting a model as DSL/VSM file Yet another option to export a model consists of using a DSL (Domain Specific Language). Valsight offers the export of a model using the VSM syntax. This export is guaranteed to successfully include all information included in a model. To export a model as a DSL file, head to the admin UI and go to the model’s settings. From there, select “Definition Download” ![DSL Download.png](./images/5094206994.png) The downloaded model definition can then be inserted into any model’s definition editor to recreate the downloaded model. To do so, click the “Definition Editor” button to open the definition editor and replace the existing text with the downloaded definition. ![Opening Definition Editor.gif](./images/5094230369.gif) ### Scenario Manager The Scenario Manager is the control terminal for your simulation calculations. Here you can create and adjust scenarios, assumptions, and line-items. You can also review and validate their effects on your base model. The Scenario Manager not only contains scenarios, assumptions, and line-items but can also export scenarios including selected models and nodes. #### Scenarios The Scenario Manager allows you to share and/or export existing scenarios. Scenarios can also be individually exported as **XLSX**, **OData,** or **CSV**. ##### Manual file download To export scenarios, click on the “Export Scenarios” button. ![Export Scenario Manager.png](./images/5094216232.png) This will open the “Export Scenarios” dialog. ![image-20220524-132550.png](./images/5094230940.png)![image-20220524-134028.png](./images/5094216403.png)![image-20220524-134156.png](./images/5094216381.png)![image-20220524-134313.png](./images/5094230920.png) ##### Exporting a scenario as an OData feed and connecting to MS Excel With OData, you can generate a link to a scenario in Valsight that is updated every time you change something in Valsight. OData is an open protocol that can be used by different software including MS Excel. In this case, Excel will be used as an example. 1. After creating a new sheet/document, go to ‘*Data*’ and click on ‘*Get Data*’. 2. Navigate to ‘*From Other Sources*’ and then ‘*From OData Feed*’ and click on it. 3. Following that, a pop-up window opens to insert the copied link you obtained from exporting a scenario. 4. Insert the link. ![excel%20odata%20grey.png?version=1\&modificationDate=1610445130475\&cacheVersion=1\&api=v2\&width=392\&height=400](./images/5094230964.png)![Enter%20Link.PNG?version=1\&modificationDate=1610445521092\&cacheVersion=1\&api=v2\&width=456\&height=150](./images/5094230968.png) In the next step, a window opens with multiple login methods. 1. Choose ‘*Basic*’ on the left side. 2. Enter your username in the upper field. 3. In the lower field, either enter your password or an API key (Read [API keys login](/api-keys-login/) on how to set up the API key). 4. Click on ‘*connect*’. ![Odata%20login%20doku.PNG?version=1\&modificationDate=1610449801928\&cacheVersion=1\&api=v2\&width=589\&height=250](./images/5094230980.png) Next, you will see a preview of the data. 1. Click on ‘*Load*’. 2. The data will now be imported into Excel. ##### Importing a scenario In the project settings, scenarios can be imported via **XLSX** files. ![image2021-12-10\_10-12-44.png](./images/5094211465.png)![Import scenario.png](./images/5094211446.png) [Please look here](/importing-scenarios/) for further information on the import of scenarios, how Valsight treats them differently than other scenarios, and potential challenges when using imported scenarios. #### Assumptions You can upload files for individual [assumptions](/creating-assumptions/), save them for later usage, or implement data changes using Excel. [Assumption](/creating-assumptions/) data can be [imported or exported as XLSX files](/excel-upload-of-assumptions-line-items/). ![ImportExport Assumption.png](./images/5094230337.png) Instead of importing or exporting individual assumptions, you can also do so for all assumptions in the Scenario Manager. The workspace-wide upload takes a **single ZIP file** holding the individual Excel files, not the `.xlsx` files themselves; its dialog is titled ‘Upload All Excel Files as a Single ZIP File’. See [Excel upload of Assumptions & Line-Items](/excel-upload-of-assumptions-line-items/). ![ImportExport All Assumptions.png](./images/5094230353.png) #### Line-Items Like assumptions, line-items can be imported or exported individually. This enables closer control over the data and, for example, changes in data. ![ImportExport Line-Item.png](./images/5094206963.png) ### Presentations The [presentation](/using-the-presentation-mode/) space has the option of importing an existing JSON file. This can be useful if you want to transfer created [presentations](/using-the-presentation-mode/). You can also export created [presentations](/using-the-presentation-mode/) as **JSON** files and print or save them as a **PDF** file. ![Upload Presentations.png](./images/5094211210.png)![Upload Presentations 2.png](./images/5094211363.png)![Print Presentation.png](./images/5094231028.png) ## Data validation Imported data have to conform to some limitations in order to be processed by Valsight. To make sure that data are correctly formatted, Valsight offers several options for validating the conformity of imported data. The most basic data validation is carried out in the data source space. Here you can validate data against your dimensions and levels to make sure Valsight can process them properly. ![Source Data Validation.png](./images/5094211119.png) Data can also be validated during the modeling of your base model. By doing so, you can make sure that your nodes contain no syntactical errors and that your source data could be calculated correctly. ![Model validation.png](./images/5094211114.png) For additional help regarding data validation, please refer to the [data validation guide](/data-dimension-validation/). ## Limitations and data upload errors Valsight allows you to build complex models and calculate simulations based on your data input. The performance of Valsight depends on the complexity of the base model and the amount of data that is calculated. In-depth information and guidelines on the technical limitations of Valsight [can be found here.](/limitations-data-sizing-guidelines/) Uploading data can sometimes fail and result in error messages or inadequate data. More information on common mistakes and errors [can be found here](/data-upload-errors-warnings-and-infos-explained/). ## Template Manager The template manager allows you to quickly save configuration settings for further use with other projects. An extensive guide on how to create templates [can be found here](/template-manager/). --- # DATE_EXTRACT URL: https://docs.valsight.ai/date-extract/ Description: Extracts the year, quarter, month, week, or day from a given time level value. **Category:** [Project variables](/project-variables/) > `DATE_EXTRACT` works only in **dynamic project variables**, not in node formulas. ## Overview The **DATE\_EXTRACT** function **extracts the year, quarter, month, week, or day from a given time level value**. Use this function in dynamic project variables when you need to derive one time level value from another (for example, the forecast year from the forecast start month). ## Syntax `DATE_EXTRACT("TimeLevelValue", "TimeLevel")` **Example usage:** `DATE_EXTRACT("$FORECAST_START", "Year")` ## Parameters | Parameter | Description | Type | Required | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------- | | **TimeLevelValue** | A value of any time level in the project's time dimension, given as a quoted string or as a variable reference (for example `"2026-01"` or `"$FORECAST_START"`). | Level value | Yes | | **TimeLevel** | The time level whose value should be returned. Allowed values: `"Year"`, `"Quarter"`, `"Month"`, `"Week"`, `"Day"`. | Level name | Yes | ## Output shape | Aspect | Behavior | | ----------- | ------------------------------ | | Return type | Level value | | Format | Format of the chosen TimeLevel | ## Watch out * `TimeLevelValue` must be a valid level value within the [project's time horizon](/changing-the-time-horizon/). * When the requested level is smaller than your input's level, the function extracts the first finer value of your input. See the "Step from a coarser to a finer level" example below. * Only time-dimension levels are accepted. Other dimensions cannot be passed here. ## Examples ### Extract the year from a month **Formula:** `DATE_EXTRACT("2026-06", "Year")` | TimeLevelValue | TimeLevel | DATE\_EXTRACT Result | | -------------- | --------- | -------------------- | | `"2026-06"` | `"Year"` | `"2026"` | ### Extract the quarter from a day **Formula:** `DATE_EXTRACT("20260515", "Quarter")` | TimeLevelValue | TimeLevel | DATE\_EXTRACT Result | | -------------- | ----------- | -------------------- | | `"20260515"` | `"Quarter"` | `"2026-Q2"` | ### Derive a value from another variable If a project has a fixed variable `$FORECAST_START = "2026-04"`, you can define a derived variable `FORECAST_YEAR` as: **Formula:** `DATE_EXTRACT("$FORECAST_START", "Year")` | TimeLevelValue | DATE\_EXTRACT Result | | -------------- | -------------------- | | `"2026-04"` | `"2026"` | The derived variable updates automatically whenever `$FORECAST_START` is changed. ### Step from a coarser to a finer level `"2026"` is a year. When you ask for a finer level (Quarter, Month, Week, or Day), the function returns the first value at that level. | Formula | DATE\_EXTRACT Result | Why | | --------------------------------- | -------------------- | ---------------------------------- | | `DATE_EXTRACT("2026", "Quarter")` | `"2026-Q1"` | Q1 is the first quarter of 2026 | | `DATE_EXTRACT("2026", "Month")` | `"2026-01"` | January is the first month of 2026 | | `DATE_EXTRACT("2026", "Day")` | `"20260101"` | January 1 is the first day of 2026 | ### Extract the quarter of the forecast end To compute the quarter that the forecast end falls in, first offset the forecast start by 12 months with [DATE\_OFFSET](/date-offset/), then extract the quarter. If `$FORECAST_START = "2026-04"`: **Formula:** `DATE_EXTRACT(DATE_OFFSET("$FORECAST_START", "Month", 12), "Quarter")` | Step | Result | | --------------------------------------------- | ----------- | | `DATE_OFFSET("$FORECAST_START", "Month", 12)` | `"2027-04"` | | `DATE_EXTRACT("2027-04", "Quarter")` | `"2027-Q2"` | The combined result is `"2027-Q2"`. ## Related | Function | When to use instead | | ----------------------------- | ---------------------------------------------------------------------------------------------------- | | [DATE\_OFFSET](/date-offset/) | When you want to offset a value forward or backward rather than return it at a different time level. | --- # DATE_OFFSET URL: https://docs.valsight.ai/date-offset/ Description: Offsets a time level value forward or backward by a number of years, quarters, months, weeks, or days. **Category:** [Project variables](/project-variables/) > `DATE_OFFSET` works only in **dynamic project variables**, not in node formulas. ## Overview The **DATE\_OFFSET** function **offsets a time level value forward or backward by a number of years, quarters, months, weeks, or days.** Use this function in dynamic project variables when one time level value should always be derived from another rather than entered manually (for example, the forecast end from the forecast start). ## Syntax `DATE_OFFSET("TimeLevelValue", "TimeLevel", Offset)` **Example usage:** `DATE_OFFSET("$FORECAST_START", "Month", 12)` ## Parameters | Parameter | Description | Type | Required | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------- | | **TimeLevelValue** | A value of any time level in the project's time dimension, given as a quoted string or as a variable reference (for example `"2026-01"` or `"$FORECAST_START"`). | Level value | Yes | | **TimeLevel** | The time level on which to offset. Allowed values: `"Year"`, `"Quarter"`, `"Month"`, `"Week"`, `"Day"`. | Level name | Yes | | **Offset** | The number of TimeLevel steps to offset by. | Integer | Yes | ## Output shape | Aspect | Behavior | | ----------- | --------------------------------------- | | Return type | Level value | | Format | Same format as the input TimeLevelValue | ## Watch out * Both `TimeLevelValue` and the resulting value must be valid level values within the [project's time horizon](/changing-the-time-horizon/). * `Offset` can be negative: positive values offset forward in time, negative values offset backward. * When the level on which you offset is smaller than your input's level, the offset starts from the first day of your input. The result is always returned at your input's level. See the "Offset a quarter by months" example below. * Only time-dimension levels are accepted. Other dimensions cannot be passed here. ## Examples ### Add one year **Formula:** `DATE_OFFSET("2026", "Year", 1)` | TimeLevelValue | TimeLevel | Offset | DATE\_OFFSET Result | | -------------- | --------- | ------ | ------------------- | | `"2026"` | `"Year"` | `1` | `"2027"` | ### Subtract one day **Formula:** `DATE_OFFSET("20260101", "Day", -1)` | TimeLevelValue | TimeLevel | Offset | DATE\_OFFSET Result | | -------------- | --------- | ------ | ------------------- | | `"20260101"` | `"Day"` | `-1` | `"20251231"` | ### Derive a forecast end from a forecast start If a project has a fixed variable `$FORECAST_START = "2026-04"`, you can define a derived variable `FORECAST_END` as: **Formula:** `DATE_OFFSET("$FORECAST_START", "Month", 12)` | TimeLevelValue | DATE\_OFFSET Result | | -------------- | ------------------- | | `"2026-04"` | `"2027-04"` | The derived variable updates automatically whenever `$FORECAST_START` is changed. ### Derive last actuals from forecast start A common pattern: the last actuals month is one month before the forecast start. **Formula:** `DATE_OFFSET("$FORECAST_START", "Month", -1)` | TimeLevelValue | DATE\_OFFSET Result | | -------------- | ------------------- | | `"2026-04"` | `"2026-03"` | ### Offset a quarter by months `"2026-Q3"` is treated as July 1 (the first day of Q3). The offset moves from that date, and the result is given back as a quarter. | Formula | DATE\_OFFSET Result | Why | | ------------------------------------- | ------------------- | ------------------------------------------------------ | | `DATE_OFFSET("2026-Q3", "Month", 1)` | `"2026-Q3"` | July 1 + 1 month = August 1, which is in Q3 | | `DATE_OFFSET("2026-Q3", "Month", -1)` | `"2026-Q2"` | July 1 - 1 month = June 1, which is in Q2 | | `DATE_OFFSET("2026-Q3", "Year", -1)` | `"2025-Q3"` | July 1 - 1 year = July 1, 2025, which is in Q3 of 2025 | ### Derive the planning year from the forecast start To compute the year after the forecast start's year, use [DATE\_EXTRACT](/date-extract/) to drop down to the Year level first, then offset by one year. If `$FORECAST_START = "2026-04"`: **Formula:** `DATE_OFFSET(DATE_EXTRACT("$FORECAST_START", "Year"), "Year", 1)` | Step | Result | | ----------------------------------------- | -------- | | `DATE_EXTRACT("$FORECAST_START", "Year")` | `"2026"` | | `DATE_OFFSET("2026", "Year", 1)` | `"2027"` | The combined result is `"2027"`. ## Related | Function | When to use instead | | ------------------------------- | -------------------------------------------------------------------------------- | | [DATE\_EXTRACT](/date-extract/) | When you want to return a value at a different time level rather than offset it. | --- # Datenquellen URL: https://docs.valsight.ai/datenquellen/ Description: Diese Seite bietet Tutorials und Anleitungen rund um das Thema Datenquellen. Diese Seite bietet Tutorials und Anleitungen rund um das Thema Datenquellen. ## Projekte verbinden mit Szenario Exporten Video: [Projekte verbinden mit Szenario Exporten](https://www.youtube.com/watch?v=Y2AZsEEdMWA) In diesem Tutorial zeigen wir dir, wie du Exporte für andere Projekte freigibst, Exportszenarien in Zielprojekte importierst und simulierte Knoten in neuen Projekten nutzen kannst. Erfahre außerdem, wie du Exporte aktualisierst und deine Datenquellen immer auf dem neuesten Stand hältst. [Mehr Details](/importing-scenarios/) und [Exporte freigeben](/sharing-exports/) --- # Default Scale Settings in Nodes URL: https://docs.valsight.ai/default-scale-settings-in-nodes/ Description: Set the scale a node's numbers are displayed at once, on the node itself, so every chart that shows it is formatted sensibly. A node's **Default Scale** sets the scale its numbers are displayed at, on the node itself. Every chart that shows the node picks it up, so you do not have to rescale each chart by hand. ## What it is Scale can be set in two places, and they work at different levels: | Where | Scope | | ----------------------------------------------- | ------------------------------------------------- | | **Scales and digits** in the chart editor | That one chart, and one scale for the whole axis. | | **Default Scale** in a node's advanced settings | Every chart that displays that node, per node. | The per-chart scale is a single setting for everything on the axis, which is the source of the problem below. The node setting is per node, so nodes of very different magnitudes can each be formatted correctly in the same chart. ## When to use it * Large numbers come out unformatted or too wide to read. * Rescaling the chart fixes the large numbers but rounds the small ones to zero. * The same node is charted in several places and you want its formatting consistent everywhere. ## Configuration 1. Open the model the node lives in. 2. Select the node and click **Show Advanced Settings**. 3. Set **Default Scale**. ![The Default Scale setting under a node's advanced settings](./images/5094193047.png) ## Good to know * **Rescaling the chart is the trap.** Raising the scale in the chart editor applies to the whole axis, so the small values on it get rounded to 0 and disappear. Here the large numbers are unformatted and the chart-level scale cannot fix both at once: ![A chart where large numbers are unformatted and small ones would round to zero](./images/5094193050.png) Setting **Default Scale** per node formats each node on its own terms: ![The same view with each node carrying its own default scale](./images/5094193053.png) * **It is a display setting.** The stored values do not change, only how they are shown. * **A model tree is where this shows up most.** Trees put nodes of very different magnitudes side by side, so a single chart-level scale rarely suits all of them. See [Model Tree](/model-tree/). ## Related * [Formatting Charts](/chart-configuration/): the per-chart scale, under Scales and axes. * [Model Tree](/model-tree/): the chart type where mixed magnitudes are most common. * [Advanced Node Settings](/advanced-node-settings/): the other settings on a node. --- # Define Calculations for a Node URL: https://docs.valsight.ai/define-calculations-for-a-node/ Description: This guide shows you how to define a calculation for a node so it computes its value based on other nodes in the model. Define a calculation for a node so it computes its value based on other nodes in the model. ## Prerequisites * The nodes you want to reference in the calculation [already exist.](/creating-nodes/) ## Steps ### Select the target node Click the node on the canvas that should contain the calculation (for example, `Revenue`). The function editor opens automatically. ### Enter the calculation formula In the function editor, type the formula using existing node names (for example, `'Volume' * 'Price'`). ### Use node references correctly Make sure each referenced node name starts and ends with an apostrophe. ### Confirm the operation Save the operation to store the calculation. ## Building a calculation by drawing a connector You can also add an input by dragging from one node's connection handle onto another. This is not only a drawing gesture: it **edits the receiving node's formula**. Dragging from `Volume` onto `Revenue` appends `+ $` to Revenue's operation, using the node's numeric id rather than its name. If Revenue had no formula yet, its operation becomes that reference alone. When the node has **Operation per baseline** switched on, every baseline's operation is changed the same way. The gesture is refused silently when you cannot edit the model, and when the link already exists. > **Drawing structure changes calculations** > > There is no way to link two nodes on the canvas without altering the target's formula. If you are sketching a model's shape and do not want the arithmetic yet, use annotations rather than connectors, or expect to edit the formula afterwards. ## What you have done The selected node now calculates its value based on the defined formula. The model reflects the calculation logic between the connected nodes. ## Troubleshooting * **Referenced node is not recognized** Check that the node name is spelled correctly and wrapped in apostrophes. * **Auto-completion does not show the node** Ensure the referenced node already exists in the model. ## Related * [Add Nodes to a Model](/creating-nodes/) * [Create a New Model 7.0](/creating-and-configuring-models/) * [Nodes](/nodes/) --- # DELTA_ABS URL: https://docs.valsight.ai/delta-abs/ Description: The DELTA_ABS function calculates the absolute difference between consecutive values within a selected dimension. The result is signed (current - previous). **Category:** [Compare periods](/compare-periods/) ## Overview The **DELTA\_ABS** function calculates the **absolute difference between consecutive values** within a selected dimension. The result is signed (`current - previous`), so values can be negative. Use this function when you need the absolute change between consecutive values along any dimension, not just time. ## Syntax `DELTA_ABS('Node', ["Dimension", ["FirstValueBehavior"]])` **Example usage:** `DELTA_ABS('Revenue')` ## Parameters | Parameter | Description | Type | Required | Default | | ---------------------- | --------------------------------------------------------------------------- | -------------- | -------- | ----------------------------------- | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Profit'`) | Node reference | Yes | -- | | **Dimension** | The dimension along which consecutive values are compared | Dimension name | No | `"Time"` at the node's finest level | | **FirstValueBehavior** | How the first value in each series of consecutive values is handled | Keyword | No | `"SKIP_FIRST"` | **FirstValueBehavior options:** * `"SKIP_FIRST"`: The first value in each series is removed from the result. This is the default. * `"FIRST_AS_ZERO"`: The first value in each series is set to zero. * `"FIRST_VALUE"`: The first value in each series is kept as it is. ## Output shape | Aspect | Behavior | | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as input. All dimensions and levels of the input are preserved. | | Granularity | The absolute difference is computed on the lowest available level of the chosen Dimension. | | Values | Each result row is `current - previous` along the chosen Dimension. Results are signed and can be negative. | | Row count | With **SKIP\_FIRST**, the first entry of each series is dropped, so row count is reduced. With **FIRST\_AS\_ZERO** and **FIRST\_VALUE**, row count is preserved. | ## Watch out * The absolute difference is always calculated on the lowest available level of the specified dimension. * The function compares **only** entries that actually exist in the input. Missing values are skipped. To calculate the absolute difference with filled missing values, use [YOY\_ABS](/yoy-abs/) for year-over-year, or fill gaps before calling DELTA\_ABS. * With **SKIP\_FIRST** (default), series that contain only a single entry are dropped from the result entirely. Use `FIRST_AS_ZERO` or `FIRST_VALUE` to keep them. * If the chosen Dimension's levels are linked from levels in another Dimension within the input, the calculation fails. In that case, calculate the delta on the linking Dimension instead. * The result will use the same level links as those defined in dimension management. Do not use this function if your node needs level links that differ from the dimension's defaults. ## Examples ### Default: skipping first values The function subtracts the value of the previous available entry from the current one, based on the order of the chosen dimension `"Time"`. Missing entries are skipped, and the first entry per series is dropped. **Input node:** `'Input node'` | Year | Month | Product | Value | | ---- | ------- | ------- | ----- | | 2025 | 2025-11 | A | -30 | | 2025 | 2025-11 | B | 2 | | 2026 | 2026-04 | A | 25 | | 2026 | 2026-05 | B | -10 | | 2026 | 2026-05 | C | 15 | **Formula:** `DELTA_ABS('Input node')` **Equivalent to:** `DELTA_ABS('Input node', "Time", "SKIP_FIRST")` | Year | Month | Product | Calculation | Result | | ---- | ------- | ------- | ----------- | ------ | | 2026 | 2026-04 | A | 25 - (-30) | 55 | | 2026 | 2026-05 | B | -10 - 2 | -12 | Product A's delta crosses zero: "ABS" means absolute (vs. relative) difference, not magnitude. Product C is missing from the output because it has only one entry, so SKIP\_FIRST drops it. ### First values as zero Using the same input node as above. With FIRST\_AS\_ZERO, the first entry per series gets a result of 0 instead of being omitted, and single-entry series are preserved. **Formula:** `DELTA_ABS('Input node', "Time", "FIRST_AS_ZERO")` | Year | Month | Product | DELTA\_ABS Result | | ---- | ------- | ------- | ----------------- | | 2025 | 2025-11 | A | 0 | | 2025 | 2025-11 | B | 0 | | 2026 | 2026-04 | A | 55 | | 2026 | 2026-05 | B | -12 | | 2026 | 2026-05 | C | 0 | Product C now appears in the result with value 0 because its single entry is treated as a "first value". ### Keeping first values Using the same input node as above. With FIRST\_VALUE, the first entry per series keeps its original value instead of being omitted or zeroed. **Formula:** `DELTA_ABS('Input node', "Time", "FIRST_VALUE")` | Year | Month | Product | DELTA\_ABS Result | | ---- | ------- | ------- | ----------------- | | 2025 | 2025-11 | A | -30 | | 2025 | 2025-11 | B | 2 | | 2026 | 2026-04 | A | 55 | | 2026 | 2026-05 | B | -12 | | 2026 | 2026-05 | C | 15 | ### Calculating deltas along a non-Time dimension DELTA\_ABS works on any dimension, not just Time. The example below uses a node that has only a Product level. Deltas are calculated along the Product order. **Input node:** `'Sales'` | Product | Value | | ------- | ----- | | A | 10 | | B | 30 | | C | 15 | **Formula:** `DELTA_ABS('Sales', "Product")` | Product | Calculation | Result | | ------- | ----------- | ------ | | B | 30 - 10 | 20 | | C | 15 - 30 | -15 | The first product (A) is dropped under the default SKIP\_FIRST. Each subsequent value is subtracted from the previous one along the Product dimension's order. ## Related | Function | When to use instead | | ------------------------- | ---------------------------------------------------------------------------------- | | [DELTA\_REL](/delta-rel/) | When you need the relative change (percentage) instead of the absolute difference. | | [YOY\_ABS](/yoy-abs/) | When you need year-over-year absolute change with filled missing values. | | [QOQ\_ABS](/qoq-abs/) | When you need absolute change specifically quarter-over-quarter. | --- # DELTA_REL URL: https://docs.valsight.ai/delta-rel/ Description: In contrast to YOY_REL and related relative functions, the growth will be calculated by using the absolute former value as relative base: (currentValue - formerValue) / absolute(formerValue). **Category:** [Compare periods](/compare-periods/) ## Overview The **DELTA\_REL** function **calculates the relative difference between consecutive values** within the selected dimension. Use this function when you need the relative (percentage) change between consecutive values along any dimension, not just time. ## Syntax `DELTA_REL('Node', ["Dimension", ["FirstValueBehavior"]])` ## Parameters | Parameter | Description | Type | Required | Default | | ---------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ----------------------------------- | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | -- | | **Dimension** | The dimension along which consecutive values are compared. | Dimension name | No | `"Time"` at the node's finest level | | **FirstValueBehavior** | How the first value per unique level combination is handled. | Keyword | No | `"SKIP_FIRST"` | **FirstValueBehavior options:** * `"SKIP_FIRST"`: The first level combination per group will not be present in the result. This is the default. * `"FIRST_AS_ZERO"`: The value of the first level combination will be set to zero. ## Watch out * The growth will always be calculated on the lowest available level of the specified dimension. * If the "former value" is zero, the calculation cannot be performed as a division by zero is not possible. The level combination will therefore not be in the result. * The function compares **only** entries that actually exist in the input. Missing values are skipped. To calculate the growth with filled missing values, use [YOY\_REL](/yoy-rel/). * The function ensures that the links from the levels of the specified dimension match those in the dimension management. Do not use this function if you want the node to have different level links as the dimensions. ## Examples ### Default: skipping first values In contrast to [YOY\_REL](/yoy-rel/) and related relative functions, the growth will be calculated by using the absolute former value as relative base: (currentValue - formerValue) / absolute(formerValue). This means for example: The relative growth from -2 to -10 is -400% as (-10 - (-2)) / abs(-2) = (-8 / 2) = -4. **Input node:** `'Input node'` | Year | Month | Product | Value | | ---- | ------- | ------- | ----- | | 2025 | 2025-11 | A | 1 | | 2025 | 2025-11 | B | 2 | | 2026 | 2026-04 | A | 20 | | 2026 | 2026-05 | B | -10 | **Formula:** `DELTA_REL('Input node')` **Equivalent to:** `DELTA_REL('Input node', "Time", "SKIP_FIRST")` | Year | Month | Product | Calculation | Result | | ---- | ------- | ------- | ------------------ | ------ | | 2026 | 2026-04 | A | (20 - 1) / ABS(1) | 19 | | 2026 | 2026-05 | B | (-10 - 2) / ABS(2) | -6 | ### First values as zero With FIRST\_AS\_ZERO, the first entry per group gets a result of 0 instead of being omitted. **Formula:** `DELTA_REL('Input node', "Time", "FIRST_AS_ZERO")` | Year | Month | Product | DELTA\_REL Result | | ---- | ------- | ------- | ----------------- | | 2025 | 2025-11 | A | 0 | | 2025 | 2025-11 | B | 0 | | 2026 | 2026-04 | A | 19 | | 2026 | 2026-05 | B | -6 | ## Related | Function | When to use instead | | ------------------------- | ------------------------------------------------------------------------ | | [DELTA\_ABS](/delta-abs/) | When you need the absolute difference instead of a percentage. | | [YOY\_REL](/yoy-rel/) | When you need year-over-year relative change with filled missing values. | | [QOQ\_REL](/qoq-rel/) | When you need relative change specifically quarter-over-quarter. | --- # DEPRECIATION URL: https://docs.valsight.ai/depreciation/ Description: The DEPRECIATION function calculates linear depreciation values per period from an investment node and a depreciation time node. The result is the depreciation amount for each time period, not the remaining book value. **Category:** [Finance functions](/finance-functions/) ## Overview The **DEPRECIATION** function **calculates linear depreciation values per period from an investment node and a depreciation time node**. The result is the depreciation amount for each time period, not the remaining book value. Depreciation from multiple investment periods stacks automatically. Use this function when you need to calculate straight-line depreciation values per period from initial investments and their depreciation times. ## Syntax `DEPRECIATION('ValueNode', 'DepreciationTime' [, "TimeLevel"])` **Example usage:** `DEPRECIATION('Investments', 'DepreciationTime')` ## Parameters | Parameter | Description | Type | Required | Default | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | -------- | | **ValueNode** | Input node with the values to depreciate over time. Must have a time level. | Node reference | Yes | -- | | **DepreciationTime** | Node containing the depreciation periods for each asset. Must **not** have a time level. Negative and non-integer values make the calculation fail; a depreciation time of 0 is accepted but produces nothing. | Node reference | Yes | -- | | **TimeLevel** | The time level to which depreciation times correspond. | Level name | No | `"Year"` | ## Output shape | Aspect | Behavior | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as ValueNode. | | Time range | Extends beyond the input data. Depreciation continues for the specified number of periods after each investment. | | Values | Linear depreciation amount per period: `investment / depreciation_periods`. Values from investments in different periods are added together where they overlap. | | Row count | Expanded. Periods beyond the last investment are included as long as depreciation is still active. | ## Watch out * The **ValueNode** must have a time level. The DepreciationTime node must **not** have a time level. * **Negative** and **non-integer** depreciation times make the calculation fail with an error naming the offending value. * A depreciation time of **0** does not error. It is accepted and silently returns 0 for every period, so an investment with a depreciation time of 0 disappears from the result without any warning. Check for zeros in the DepreciationTime node before you trust an empty result. * When **TimeLevel is omitted**, depreciation times are assumed to be in years. If the ValueNode is at Quarter or Month granularity, the depreciation times are automatically converted (e.g. 4 years becomes 16 quarters or 48 months). * The result is the **depreciation amount per period**, not the remaining book value. To get the remaining book value, subtract the cumulative depreciation (using [RUNNINGSUM](/runningsum/)) from the original investment. * The DepreciationTime node must not be more fine-grained than the ValueNode. ## Examples ### Overlapping depreciation from yearly investments Two investments made in consecutive years are each depreciated over 4 periods. The result shows how depreciation amounts from different investments stack up. **Input node:** `'Investments'` | Year | Value | | ---- | ----- | | 2025 | 1000 | | 2026 | 400 | **Input node:** `'DepreciationTime'` | Periods | | ------- | | 4 | **Formula:** `DEPRECIATION('Investments', 'DepreciationTime')` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | N/A | 250 | | 2026 | 250 + 100 | 350 | | 2027 | 250 + 100 | 350 | | 2028 | 250 + 100 | 350 | | 2029 | N/A | 100 | | 2030 | N/A | 0 | Each investment is divided by 4 periods: 1000/4 = 250, 400/4 = 100. From 2026 to 2028 both depreciation streams overlap. ### Per-category depreciation times Two asset categories with different depreciation times show that each category is depreciated independently based on its own period count. **Input node:** `'Investments'` | Year | Category | Value | | ---- | -------- | ----- | | 2026 | A | 2000 | | 2026 | B | 1000 | **Input node:** `'DepreciationTime'` | Category | Periods | | -------- | ------- | | A | 2 | | B | 4 | **Formula:** `DEPRECIATION('Investments', 'DepreciationTime')` | Year | Category | DEPRECIATION Result | | ---- | -------- | ------------------- | | 2026 | A | 1000 | | 2026 | B | 250 | | 2027 | A | 1000 | | 2027 | B | 250 | | 2028 | A | 0 | | 2028 | B | 250 | | 2029 | A | 0 | | 2029 | B | 250 | | 2030 | A | 0 | | 2030 | B | 0 | Category A is fully depreciated after 2 periods, while Category B continues for 4 periods. ## Related | Function | When to use instead | | -------------------------- | ------------------------------------------------------------------------------------------------------------ | | [RUNNINGSUM](/runningsum/) | Combine with DEPRECIATION to calculate remaining book value: `'Investment' - RUNNINGSUM(DEPRECIATION(...))`. | --- # Digitally Signed Releases URL: https://docs.valsight.ai/digitally-signed-releases/ Description: All our releases are digitally signed using a GPG key to ensure authenticity and integrity. You can verify that the files you download have not been tampered… All our releases are digitally signed using a GPG key to ensure authenticity and integrity. You can verify that the files you download have not been tampered with by checking the signature against our public key. The public key has ID: A31F5ED57BD4386068186B4640D0B4DE7E47274F [Valsight\_GmbH\_Releases\_-\_Level\_1.pub](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/6189023283_Valsight_GmbH_Releases_-_Level_1.pub) To verify a signature: ``` # Import the public key into the local key store gpg --import Valsight_GmbH_Releases_-_Level_1.pub # Verify the signature, replace X.X.X with version number gpg --verify valsight-server.sig valsight-server-X.X.X.zip ``` > You must not re-import the Public Key each time you download a new release. In fact, for improved security, it is recommended to verify the correctness of the public key via a separate channel (Email, Phone) once and then keep the local, trusted version. --- # Dimensionality & hierarchies URL: https://docs.valsight.ai/dimensionality-hierarchies/ Description: Use this category when you need to control a formula’s output shape: which dimensions and levels the result has, and at what granularity values exist. Use this category when you need to **control a formula’s output shape**: which dimensions and levels the result has, and at what granularity values exist. These functions let you aggregate to higher levels, remove detail, expand values to more detailed intersections, or distribute values across level values. ## Start here if you want to: * Fix a result that is **too aggregated**, with less detail than you expected * Fix a result that is **too granular**, with more detail than you expected * Make two nodes combine cleanly when they **have different dimensionality** * **Prepare a node for simulation** by creating the full dimensional space ## Not here if you want to: * Apply a numeric transformation such as scaling, rounding, or ratios → see [Math & numeric](/math-numeric/) * Pick a subset of level values → see [Filtering & data shaping](/filtering-data-shaping/) ## Mental model * **Roll up**: aggregate to higher levels * **Drop**: remove levels from a dimension to simplify the shape * **Expand**: add detail by creating combinations of level values * **Distribute**: allocate values down to more detailed level values using a distribution key * **Rebook**: move values between level values within the same level ## Common patterns | Name | What it does | Formula | | ------------------------------------ | ----------------------------------------------------------------------------- | ------------------------------------------------- | | Aggregate to a higher level | Use when you want values only at selected higher levels. | `ROLLUP('Node', "Level")` | | Match another node’s shape | Use when you want one node aggregated to another node’s dimensionality. | `ROLLUP_TO('Node', 'TargetShapeNode')` | | Remove unwanted granularity | Use when a node carries detail you don’t want in further calculations. | `DROPLEVEL('Node', "Level")` | | Expand to more detail | Use when you need a value available at a more detailed level. | `EXPAND('Node', "Level")` | | Expand only to specific level values | Use when you want targeted expansion without creating the full cross product. | `EXPANDSINGLE('Node', "Level", ["A", "B"])` | | Create an empty simulation space | Use when you want to initialize a node with the required dimensionality. | `EXPAND(0, "Level1", "Level2")` | | Allocate totals down to detail | Use when you want allocations that preserve totals but add detail. | `DISTRIBUTE('OriginalNode', 'DistributionNode')` | | Move values between level values | Use when you need to reclassify values within the same level. | `REBOOK('Node', "Level", "OldValue", "NewValue")` | ## Functions in this category | Function | Description | | ------------------------------ | --------------------------------------------------------------------------------------------- | | [EXPAND](/expand/) | Expands a node or a specified value by adding the full cross product of the specified levels. | | [EXPANDSINGLE](/expandsingle/) | Expands a node or a value to the specified level values. | | [DROPLEVEL](/droplevel/) | Removes one or more levels (and any finer levels in the same dimension) from the node. | | [ROLLUP](/rollup/) | Aggregates a node to only the specified levels. | | [ROLLUP\_TO](/rollup-to/) | Aggregates the first node to match the level dimensionality of the second node. | | [DISTRIBUTE](/distribute/) | Distributes values of one node across levels based on another node’s value distribution. | | [REDISTRIBUTE](/redistribute/) | Redistributes a value within specified clusters, weighted by a distribution measure. | | [REBOOK](/rebook/) | Rebooks numeric values from one level value to another within the same level. | ## Choosing between similar functions **ROLLUP vs DROPLEVEL** * Use `ROLLUP` when you want an explicit aggregation target * Use `DROPLEVEL` when you want to remove specific granularity from a dimension **EXPAND vs EXPANDSINGLE** * Use `EXPAND` when you want the full cross product for a level * Use `EXPANDSINGLE` when you only want specific level values **ROLLUP vs ROLLUP\_TO** * Use `ROLLUP` when you know the target levels * Use `ROLLUP_TO` when another node already defines the target shape **DISTRIBUTE vs REDISTRIBUTE** * Use `DISTRIBUTE` to allocate values down using a distribution key * Use `REDISTRIBUTE` when allocation should happen only within defined clusters **REBOOK vs DISTRIBUTE** * Use `REBOOK` when you want to move values from one level value to another * Use `DISTRIBUTE` or `REDISTRIBUTE` when you want to split totals across multiple level values using weights ## Pitfalls & troubleshooting * **Result is too aggregated:** check whether `+` or `-` aligned to shared dimensions; make the intended shape explicit with `ROLLUP` or `ROLLUP_TO` * **Result is too granular or too large:** check whether `*` or `/` expanded across combined dimensions or whether an `EXPAND` added more detail than intended * **Result is empty after reshaping:** confirm referenced levels/level values exist and labels match exactly (spelling/case) * **Unexpected allocation results:** verify the distribution key node has values at the target detail and that totals behave as expected after distribution * **Element-wise adjustment needed:** use `ADDEACH` rather than relying on `+ constant` behavior ## Related * [Filtering & data shaping](/filtering-data-shaping/): subset selection and fill or pick helpers * [Operators](/operators/): alignment behavior and comparisons used inside formulas * [Troubleshooting guide](/troubleshooting-guide/): wrong shape and missing values * [Function catalog](/function-catalog/): full signatures, parameters, and examples --- # Dimensions URL: https://docs.valsight.ai/dimensions/ Description: Dimensions in Valsight structure data into cluster such as product, region, or time, so values can be organized, aggregated, and analyzed across different vi… **Dimensions** in Valsight **structure data into cluster** such as product, region, or time, so values can be organized, aggregated, and analyzed across different views. ![image-20260415-194500.png](./images/7008452653.png) ## Start here if you want to: | If you | Go to | | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | Understand what a dimension is and the vocabulary around it | [How dimensions work](/how-dimensions-work/) | | Understand how the Time dimension is generated and which levels it has | [The time dimension](/time-dimension/) | | Get guidance on structuring a dimension well | [Best practices for dimensions](/best-practices-for-dimensions/) | | Create a new dimension | [Creating dimensions](/creating-maintaining-dimensions/) | | Bulk-update a dimension via Excel | [Updating level values via data source upload](/updating-level-values-via-data-source-upload/) | | Attach linked levels (attributes) to a dimension | [Linked levels](/linked-levels/) | ## Who this section is for This section is for users who define, structure, or maintain dimensions in Valsight. Because dimensions are referenced by every subsystem that handles data (data sources, models, workspaces), anyone working in those areas benefits from understanding the dimensions their work depends on. --- # DISAGGREGATE URL: https://docs.valsight.ai/disaggregate/ Description: Disaggregates the values of the Original Node for the given Level based on the value distribution from the Distribution Node, in relation to the aggregated values of the Distribution Node when rolled up to the levels of the Original Node. **Category:** [Assumptions & result sets](/assumptions-result-sets/) > **Legacy function** > > This function is sustained only for compatibility purposes. Please use the newer function [DISTRIBUTE](/distribute/) instead. ## Overview The **DISAGGREGATE** function **disaggregates the values of the Original Node for the given Level based on the value distribution from the Distribution Node**, in relation to the aggregated values of the Distribution Node when rolled up to the levels of the Original Node. Can be used to redistribute values that are not available on a certain level. An example is the assignment of OPEX to products according to their revenue. Use this function when you need to allocate values from a higher level to a more detailed level based on an existing distribution. ## Syntax `DISAGGREGATE('OriginalNode', "Level", 'DistributionNode')` ## Parameters | Parameter | Description | Type | Required | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | | **OriginalNode** | Input node, specified using the node name in single quotes (e.g. `'OPEX'`) | Node reference | Yes | | **Level** | Level by which the OriginalNode should be disaggregated, i.e. the level which should exist on the node after application of the function (e.g. `"Product"`) | Level name | Yes | | **DistributionNode** | Node by whose distribution the values of the OriginalNode should be disaggregated, specified using the node name in single quotes (e.g. `'Revenue'`) | Node reference | Yes | ## Watch out * The function groups the values according to all shared levels of `OriginalNode` and `DistributionNode`. In the example given here, this is the `"Year"` level, and hence the distribution is applied to each year individually. If both nodes share a hierarchy but have different levels, the `DistributionNode` needs to have the finer level and is rolled up to match the level of `OriginalNode`. ## Examples ### Disaggregate annual OPEX to products This example shows how annual OPEX values are distributed to the product level based on the revenue mix in each year. The distribution is calculated separately for each year because both input nodes share the `'Year'` level. **Input node:** `'OPEX'` | Year | Value | | ---- | ----- | | 2025 | 4000 | | 2026 | 8000 | **Input node:** `'Revenue'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | M1 | 100 | | 2025 | M2 | 300 | | 2025 | Z3 | 400 | | 2026 | M1 | 200 | | 2026 | M2 | 600 | | 2026 | Z3 | 800 | **Formula:** `DISAGGREGATE('OPEX', "Product", 'Revenue')` | Year | Product | DISAGGREGATE Result | | ---- | ------- | ------------------- | | 2025 | M1 | 500 | | 2025 | M2 | 1500 | | 2025 | Z3 | 2000 | | 2026 | M1 | 1000 | | 2026 | M2 | 3000 | | 2026 | Z3 | 4000 | ## Related | Function | When to use instead | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | [DISTRIBUTE](/distribute/) | When you want the modern replacement that covers the same use case with clearer behavior and fewer legacy limitations. | | [ROLLUP](/rollup/) | When you want to aggregate values to a higher level instead of distributing them to a more detailed one. | --- # Displaying Scenarios in the Data Preview URL: https://docs.valsight.ai/displaying-scenarios-in-the-data-preview/ Description: When building a model, it can be helpful to directly see data from a simulation scenario in the data preview of nodes. When building a model, it can be helpful to directly see data from a simulation scenario in the data preview of nodes. To make simulation scenarios available in the model, go to the workspace overview, navigate to the workspace settings via the three dot menu and check "Show scenarios in model editor". Now head back to the model. ![image-20250916-134720.png](./images/6248235044.png) If you open the Data Preview of a node, the dropdown "Workspace Scenario" will list all scenarios from workspaces with the option "Show scenarios in model editor" enabled (listing always the workspace name and the scenario name). Select the scenario that you want to preview. For example, we can compare the Gross Profit in our "Basic" scenario with the "Best Case" scenario. ![image-20250916-134343.png](./images/6247972892.png)![image-20250916-134611.png](./images/6247972898.png) --- # DISTRIBUTE URL: https://docs.valsight.ai/distribute/ Description: The DISTRIBUTE function distributes the values of the Original Node based on the value distribution from the Distribution Node, in relation to the aggregated values of the Distribution Node when rolled up to the levels of the Original Node. **Category:** [Dimensionality & hierarchies](/dimensionality-hierarchies/) ## Overview The **DISTRIBUTE** function **distributes the values of the Original Node based on the value distribution from the Distribution Node** in relation to the aggregated values of the Distribution Node when rolled up to the levels of the Original Node. Use this function when you want to allocate aggregated values down to more detailed level values based on a weighting node. ## Syntax `DISTRIBUTE('OriginalNode', 'DistributionNode' [, "Level1", ...])` **Example usage:** `DISTRIBUTE('OPEX', 'Revenue', "Product")` ## Parameters | Parameter | Description | Type | Required | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | | **Original Node** | Input node whose values should be distributed, specified in single quotes (e.g.`'OPEX'`) | Node reference | Yes | | **Distribution Node** | Node whose value distribution provides the weights for disaggregation (e.g.`'Revenue'`). Must contain all levels of the Original Node. | Node reference | Yes | | **Level** | One or more level names to restrict which levels the Original Node is distributed to (e.g.`"Product"`). If not specified, all additional levels in the Distribution Node are used. | Level name | No | ## Output shape | Aspect | Behavior | | -------------- | ----------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Increases. The output contains all levels from the Original Node plus the distribute levels from the Distribution Node. | | Values | Each input value is split proportionally based on the weights in the Distribution Node. The total sum is preserved. | | Row count | Expands to include one row per combination of original levels and distribute level values. | ## Watch out * Values with **missing partners** in the Distribution Node will be **evenly distributed** to all values in the respective dimension level. This can create a large data set with sparse inputs. * When the **sum of distribution weights is zero** for a partition, the input value is distributed evenly across all non-null entries in that partition. * The Distribution Node must contain **all levels** of the Original Node. If it is coarser than the Original Node in any dimension, a validation error occurs. * The Original Node must **not already have** the distribute level. You cannot distribute to a level that already exists on the input. * If the distribution is executed on a dimension with a hierarchy and the chosen distribute level is a higher level, the distribution is calculated on the **lowest shared level** and afterwards aggregated to the specified level. * Filters on the distribute level's dimension are removed during calculation and applied to the result afterwards. ## Examples ### Distribute across all additional levels This example distributes OPEX to the detailed product level using revenue as the weighting node. **Input node:** `'OPEX'` | Year | OPEX | | ---- | ----- | | 2025 | 2000 | | 2026 | 4000 | | 2027 | 12000 | **Input node:** `'Revenue'` | Product Line | Product | 2025 | 2026 | | ------------ | ------- | ---- | ---- | | M | M1 | 100 | 200 | | M | M2 | 300 | 600 | | Z | Z3 | 400 | 800 | **Formula:** `DISTRIBUTE('OPEX', 'Revenue')` | Product Line | Product | 2025 | 2026 | 2027 | | ------------ | ------- | ---------------------------- | ----------------------------- | -------------------- | | M | M1 | 2000 \* 100 / 800 = **250** | 4000 \* 200 / 1600 = **500** | 12000 / 4 = **3000** | | M | M2 | 2000 \* 300 / 800 = **750** | 4000 \* 600 / 1600 = **1500** | 12000 / 4 = **3000** | | Z | Z3 | 2000 \* 400 / 800 = **1000** | 4000 \* 800 / 1600 = **2000** | 12000 / 4 = **3000** | | X | X4 | - | - | 12000 / 4 = **3000** | | **Totals** | | **2000** | **4000** | **12000** | For 2025 and 2026, each product's share is calculated as: OPEX \* (product revenue / total revenue). For 2027, no revenue data exists, so the value is evenly distributed across all 4 products. The totals are preserved in every year. ### Restrict the distribution to selected levels This example restricts the distribution to `"Product Line"`, so the result stays aggregated at product-line level instead of distributing down to each product. **Formula:** `DISTRIBUTE('OPEX', 'Revenue', "Product Line")` | Product Line | 2025 | 2026 | 2027 | | ------------ | ---------------------------- | ----------------------------- | -------------------- | | M | 2000 \* 400 / 800 = **1000** | 4000 \* 800 / 1600 = **2000** | 12000 / 3 = **4000** | | Z | 2000 \* 400 / 800 = **1000** | 4000 \* 800 / 1600 = **2000** | 12000 / 3 = **4000** | | X | - | - | 12000 / 3 = **4000** | | **Totals** | **2000** | **4000** | **12000** | By specifying `"Product Line"` instead of `"Product"`, the distribution stays at the coarser level. Revenue for product line M is the sum of M1 and M2 (100 + 300 = 400 in 2025). Totals are again preserved. ## Related | Function | When to use instead | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | [REDISTRIBUTE](/redistribute/) | When allocation should happen only within defined clusters or groups instead of across the full available detail. | | [REBOOK](/rebook/) | When values should be moved from one level value to another instead of being split across multiple level values using weights. | --- # DIVIDE URL: https://docs.valsight.ai/divide/ Description: The DIVIDE function extends the / operator with optional validation for missing rows. It produces the same result as 'Node1' / 'Node2' when validation passes. When validation fails, it produces an error with a detailed explanation of which rows are missing. **Category:** [Math & numeric](/math-numeric/) ## Overview The **DIVIDE** function **extends the** `/` **operator with optional validation for missing rows.** It produces the same result as `'Node1' / 'Node2'` when validation passes. When validation fails, it produces an error with a detailed explanation of which rows are missing. Use this function when you want the result of regular division but need explicit mismatch validation and clearer error messages. ## Syntax `DIVIDE('Node1', 'Node2' [, "Validation"])` **Example usage:** `DIVIDE('Profit', 'Revenue', "FailOnMissing")` ## Parameters | Parameter | Description | Type | Required | Default | | -------------- | ---------------------------------------------------------------------------------- | -------------- | -------- | ---------------- | | **Node1** | Dividend node, specified using the node name in single quotes (e.g.`'Profit'`) | Node reference | Yes | -- | | **Node2** | Divisor node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | -- | | **Validation** | Controls how mismatches between the two input nodes are handled. Case-insensitive. | Keyword | No | `"NoValidation"` | **Validation options:** * `"NoValidation"`: No mismatch check. Behaves exactly as the `/` operator. This is the default. * `"FailOnMissingFirst"`: Fails if any row in Node1 has no matching row in Node2. * `"FailOnMissingSecond"`: Fails if any row in Node2 has no matching row in Node1. * `"FailOnMissing"`: Fails if either node has rows not matched by the other (combines both checks). ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | Dimensionality | **Union** of all dimensions from both inputs (same as `/`). Per shared dimension, the **finest** level is used. | | Level values | Matched on shared dimensions. Non-shared dimensions are applied across all matching rows. | | Row count | Equal or reduced. Where the dividend is missing, the result is **0**. Where the divisor is missing or zero, the cell is **dropped** (N/A). | ## Watch out * Using validation has a **performance impact**. Only use it when you need to detect mismatches. * Without validation (or with `NoValidation`), DIVIDE is identical to `/`. * Missing values are handled **asymmetrically**: a missing dividend produces **0**, but a missing or zero divisor produces **N/A** (the cell is dropped). This means the result can have fewer rows than either input. * **Division by zero returns N/A** (the cell is silently dropped). If you need explicit handling, wrap in an IF condition: `IF('Divisor' != 0, DIVIDE('Dividend', 'Divisor'), 0)`. ## Examples ### Validation behavior This example shows the standard division result and how the different validation modes behave when rows are missing on one side. The underlying numeric result matches regular division as long as the selected validation passes. **Input node:** `'Node1'` | Year | Value | | ---- | ----- | | 2026 | 6 | | 2027 | 4 | | 2028 | 10 | **Input node:** `'Node2'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 3 | | 2027 | 1 | **Formula:** `'Node1' / 'Node2'` **Equivalent to:** `DIVIDE('Node1', 'Node2')` **Equivalent to:** `DIVIDE('Node1', 'Node2', "NoValidation")` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | N/A / 2 | 0 | | 2026 | 6 / 3 | 2 | | 2027 | 4 / 1 | 4 | Year 2028 is not in the result because the divisor is missing (N/A). **Formula:** `DIVIDE('Node1', 'Node2', "FailOnMissing")` **Error:** Year 2028 from Node1 has no matching value in Node2 and year 2025 from Node2 has no matching value in Node1. **Formula:** `DIVIDE('Node1', 'Node2', "FailOnMissingFirst")` **Error:** Year 2028 from Node1 has no matching value in Node2. **Formula:** `DIVIDE('Node1', 'Node2', "FailOnMissingSecond")` **Error:** Year 2025 from Node2 has no matching value in Node1. ## Related | Function | When to use instead | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [DIVISION (/)](/division/) | When you want standard division without additional validation handling or detailed mismatch errors. | | [RATIO](/ratio/) | When you want to divide two nodes while retaining only the dimensions shared by both inputs instead of using DIVIDE's regular division-with-validation behavior. | --- # DIVISION (/) URL: https://docs.valsight.ai/division/ Description: The DIVISION operator divides one input by another across their combined dimension set. In other words, division uses the union of both inputs’ dimensions. **Category:** [Arithmetic operators](/arithmetic-operators/) ## Overview The **DIVISION** operator **divides one input by another** across their **combined dimension set**. In other words, division uses the **union** of both inputs’ dimensions. The result keeps the **finer** level in each shared dimension and retains dimensions that exist on only one side. Use this operator for standard division without additional validation handling. ## Syntax `'Node1' / 'Node2'` **Example usage:** `'Profit' / 'Revenue'` ## Parameters | Parameter | Description | Type | Required | | --------- | ------------------------------------------------------------------------------ | -------------- | -------- | | **Node1** | Dividend node, specified using the node name in single quotes (e.g.`'Profit'`) | Node reference | Yes | | **Node2** | Divisor node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | The result uses the **combined dimension set** (the **union** of both inputs’ dimensions). Per shared dimension, the **finer** level is used. Dimensions that exist on only one side are kept as-is. | | Level values | Values are matched on shared dimensions. Non-shared dimensions expand the result across matching rows. | | Row count | Equal or expanded. Cells where the divisor is zero or missing become `N/A`; cells where only the **dividend** is missing become `0`. | ## Watch out * Division uses the **combined dimension set** (**union**), not the common dimensions. This is the opposite of addition and subtraction. * If one input has additional dimensions, the result expands to keep them. * Division by zero returns `N/A`. * **A missing dividend returns `0`, not `N/A`.** Division joins the two sides in full, so the result also contains rows that exist only on the divisor's side. Where the divisor is a real non-zero number and the dividend is simply absent, the cell is a defined `0`. `'Profit' / 'Revenue'` therefore reports a hard 0% margin at every intersection where Profit is missing, instead of leaving it blank. * If you need explicit fallback handling, wrap the division in an `IF` condition, for example `IF('Divisor' != 0, 'Dividend' / 'Divisor', 0)`. * Units are divided together as well. For example, `EUR` / `Quantity` produces the combined unit `EUR / Quantity`. ## Examples ### Dividing nodes with matching dimensions **Input node:** `'Node1'` | Year | Value | | ---- | ----- | | 2025 | 6 | | 2026 | 4 | **Input node:** `'Node2'` | Year | Value | | ---- | ----- | | 2025 | 3 | | 2026 | 1 | **Formula:** `'Node1' / 'Node2'` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 6 / 3 | 2 | | 2026 | 4 / 1 | 4 | ### Dividing nodes with some shared dimensions This example shows how division keeps the finer dimensionality from `Node1`. **Input node:** `'Node1'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | A | 4 | | 2025 | B | 0 | | 2026 | A | 4 | | 2026 | B | 16 | **Input node:** `'Node2'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 4 | **Formula:** `'Node1' / 'Node2'` | Year | Product | Calculation | Result | | ---- | ------- | ----------- | ------ | | 2025 | A | 4 / 2 | 2 | | 2025 | B | 0 / 2 | 0 | | 2026 | A | 4 / 4 | 1 | | 2026 | B | 16 / 4 | 4 | ### Dividing by a scalar When one input is a scalar value, that value is applied across all rows of the other input. **Input node:** `'Node1'` | Year | Value | | ---- | ----- | | 2025 | 4 | | 2026 | 8 | **Input node:** `'Node2'` | Value | | ----- | | 2 | **Formula:** `'Node1' / 'Node2'` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 4 / 2 | 2 | | 2026 | 8 / 2 | 4 | ## Related | Function | When to use instead | | ------------------ | -------------------------------------------------------------------------------------------------------------- | | [DIVIDE](/divide/) | When you want the same basic division result but with optional mismatch validation and clearer error messages. | | [RATIO](/ratio/) | When only the dimensions shared by both inputs should be retained instead of using the combined dimension set. | --- # DROPLEVEL URL: https://docs.valsight.ai/droplevel/ Description: DROPLEVEL removes one or more levels from a node and aggregates the remaining values. When a parent level is removed, all finer levels in the same hierarchy are automatically removed as well. **Category:** [Dimensionality & hierarchies](/dimensionality-hierarchies/) ## Overview The **DROPLEVEL** function **removes one or more levels** from a node **and aggregates the values of the remaining levels.** When a level is removed, all finer levels in the same hierarchy are also removed automatically (e.g. removing Quarter also removes Month and Day). Use this function when you know which levels to remove from your data rather than which to keep. ## Syntax `DROPLEVEL('Node', "Level1" [, "Level2", ...] [, "AggregationType"])` **Example usage:** `DROPLEVEL('Revenue', "Product")` ## Parameters | Parameter | Description | Type | Required | Default | | ----------------------- | ------------------------------------------------------------------------------------ | -------------- | -------- | ----------------------------------------------- | | **Node** | Input node, specified in single quotes (e.g. `'Revenue'`) | Node reference | Yes | -- | | **Level1, Level2, ...** | Level names to remove from the output, specified in double quotes (e.g. `"Product"`) | Level name | Yes | -- | | **AggregationType** | Aggregation method for combining values | String | No | Node's own aggregation type (typically `"SUM"`) | **See also:** [Aggregation Settings](/aggregation-settings/) for all available aggregation methods ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------- | | Dimensionality | Specified levels (and any finer levels in the same hierarchy) are removed | | Values | Remaining values are aggregated | | Row count | Reduced | ## Watch out * Removing a level also **removes all finer levels** below it in the hierarchy. * DROPLEVEL specifies what to remove. If you want to specify what to keep, use **ROLLUP** instead. * The **default aggregation** is the node's own aggregation type (typically SUM). Use the AggregationType parameter when you need a different method. ## Examples **Input node:** `'Revenue'` | Month | Product | Value | | ------- | ------- | ----- | | 2025-01 | Alpha | 50 | | 2025-02 | Alpha | 45 | | 2025-01 | Beta | 40 | | 2025-02 | Beta | 54 | ### Remove the product dimension To see total revenue per month regardless of product, remove the Product level: **Formula:** `DROPLEVEL('Revenue', "Product")` | Month | Calculation | Result | | ------- | ----------- | ------ | | 2025-01 | 50 + 40 | 90 | | 2025-02 | 45 + 54 | 99 | ### Removing a parent level cascades to finer levels To roll monthly revenue up to a single figure per product and year, remove the Quarter level. Because Month is finer than Quarter in the same hierarchy, it is also removed automatically. **Input node:** `'Revenue'` | Year | Quarter | Month | Product | Value | | ---- | ------- | ------- | ------- | ----- | | 2025 | Q1 | 2025-01 | Alpha | 50 | | 2025 | Q1 | 2025-02 | Alpha | 45 | | 2025 | Q1 | 2025-03 | Alpha | 60 | | 2025 | Q1 | 2025-01 | Beta | 40 | | 2025 | Q1 | 2025-02 | Beta | 54 | | 2025 | Q1 | 2025-03 | Beta | 35 | **Formula:** `DROPLEVEL('Revenue', "Quarter")` | Year | Product | Calculation | Result | | ---- | ------- | ------------ | ------ | | 2025 | Alpha | 50 + 45 + 60 | 155 | | 2025 | Beta | 40 + 54 + 35 | 129 | Both Quarter and Month are removed because Month is a finer level within the same hierarchy. **Year stays**: DROPLEVEL rolls the values up to the level directly above the coarsest level you removed, so the result is one figure per product *per year*, not one across all time. To lose the time dimension altogether, remove `"Year"` instead, the top level of the hierarchy. ### Using AVG instead of SUM To find each product's average monthly revenue instead of the total, remove the Month level. Quarter sits directly above Month, so the result is one average per product and quarter. **Input node:** `'Revenue'` | Month | Product | Value | | ------- | ------- | ----- | | 2025-01 | Alpha | 50 | | 2025-02 | Alpha | 45 | | 2025-01 | Beta | 40 | | 2025-02 | Beta | 54 | **Formula:** `DROPLEVEL('Revenue', "Month", "AVG")` | Quarter | Product | Calculation | Result | | ------- | ------- | ------------- | ------ | | 2025-Q1 | Alpha | (50 + 45) / 2 | 47.5 | | 2025-Q1 | Beta | (40 + 54) / 2 | 47 | ## Related | Function | When to use instead | | ------------------------- | -------------------------------------------------------------------------------- | | [ROLLUP](/rollup/) | When you know which levels to keep rather than remove. | | [ROLLUP\_TO](/rollup-to/) | When you want to match another node's dimensional structure automatically. | | [EXPAND](/expand/) | When you need to add levels instead of removing them (the inverse of DROPLEVEL). | --- # Duplicating a Project URL: https://docs.valsight.ai/duplicating-a-project/ Description: To duplicate a project, navigate to the three-dot menu on the project card and click on “Duplicate”. Duplicate an existing Valsight project, either in full or with only selected workspaces. ## Steps ### Duplicate a project 1. Open the three-dot menu on the project card. 2. Click **Duplicate**. 3. Confirm the duplication in the dialog that appears. ![image2021-7-29\_12-52-18.png](./images/5094206867.png) ### Duplicate with selected workspaces If you do not want to duplicate the entire project, including all [Workspaces](/workspaces/), duplicate it from the project settings instead: 1. Open the Valsight settings and go to the project settings overview. ![Configuration page v2.16.png](./images/5094217997.png) 2. Select the project you want to duplicate from the list on the left. 3. Click **Duplicate**. ![Projects v2.16.png](./images/5094217975.png) 4. In the dialog, enter a name and business key for the duplicate. 5. Select which workspaces to include in the duplicate. ![image2021-7-29\_13-11-41.png](./images/5094206923.png) 6. Click **Duplicate** to finish. ## What you have done The duplicated project appears in the Project overview, with the name and business key you assigned. --- # Editing the color palette URL: https://docs.valsight.ai/editing-the-color-palette/ Description: You can customize the color palette used in the application to change existing colors or to add your corporate colors. Go to Configuration Your project Set… You can customize the color palette used in the application to change existing colors or to add your corporate colors. Go to Configuration > Your project > Settings > Appearance: themeCustomColorPalettes. This example contains the default colors with two empty entries titled "Your Color". Change it and paste it into the textfield. ```js { "chartColors": [ { "hex": "#00537e", "name": "dark blue" }, { "hex": "#058ece", "name": "blue" }, { "hex": "#1dcbf1", "name": "light blue" }, { "hex": "#b2e7dd", "name": "light green" }, { "hex": "#006352", "name": "green" }, { "hex": "#6e2810", "name": "dark red" }, { "hex": "#c83e2d", "name": "red" }, { "hex": "#fd7e26", "name": "orange" }, { "hex": "#ffb768", "name": "light orange" }, { "hex": "#ffdf47", "name": "yellow" }, { "hex": "#494949", "name": "dark grey" }, { "hex": "#818181", "name": "grey" }, { "hex": "#d5d5d5", "name": "light grey" }, { "hex": "#000000", "name": "black" }, { "hex": "#XXXXXX", "name": "Your Color" } ], "tableBackgroundColors": [ { "hex": "#ffffff", "name": "white" }, { "hex": "#b8d6e5", "name": "blue" }, { "hex": "#b2e7dd", "name": "green" }, { "hex": "#e5c3b8", "name": "red" }, { "hex": "#fff6cc", "name": "yellow" }, { "hex": "#818181", "name": "grey" }, { "hex": "#d5d5d5", "name": "light grey" }, { "hex": "#XXXXXX", "name": "Your Color" } ] } ``` The *chartColors* are used as the colors for scenarios, charts and sheets in the workspace and nodes in the model. The *tableBackgroundColors* are used as column background colors for tables in the workspace. | Default colors | A customized palette | | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | | ![The default Valsight color palette in the color picker](./images/5094214031.png) | ![The same color picker after corporate colors were added to the palette](./images/5094214026.png) | *Tip: To pick up colors from an existing design, use a web service such as [TinEye Color Extraction](https://labs.tineye.com/color/) to extract all color codes from a screenshot.* --- # Einführung URL: https://docs.valsight.ai/einfuehrung/ Description: Einführung [Einführung.pdf](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989793801_Einfuehrung.pdf) [Personal data.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989793808_Personal-data.xlsx) [Personal dim.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989826573_Personal-dim.xlsx) [KBA.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5990383628_KBA.xlsx) --- # Entra / AAD Configuration URL: https://docs.valsight.ai/entra-aad-configuration/ Description: Create a new Application registration, and provide Valsight with the following information: > **Looking for cloud SSO?** This page describes the direct-to-instance setup, in which Entra talks to your Valsight instance. If your Valsight runs in the cloud, your identity provider connects through Valsight ID instead and there is one redirect URL rather than the per-edition callback URLs below — see [Cloud SSO with Valsight ID](/cloud-openid-connect/). Configure Microsoft Entra (formerly Azure AD) as Valsight's identity provider: register the application, set the callback URL for your deployment edition, and pass group claims through. ## Basic configuration Create a new Application registration, and provide Valsight with the following information: * Application (client) ID (= clientId) * clientSecret * Directory (tenant) ID (= appId) Your Valsight Contact will provide you with the callback URLs relevant for your instance. You must add the callback URLs to your Entra Configuration. The structure of of callback URLs: #### Corporate Edition ``` https://cloud.valsight.com//login/oauth2/code/openIdConnect https://cloud.valsight.com/-restore/login/oauth2/code/openIdConnect (restore endpoint) ``` #### Enterprise Edition Open Telekom Cloud ``` https://.valsight.cloud/login/oauth2/code/openIdConnect https://-restore.valsight.cloud/login/oauth2/code/openIdConnect (restore endpoint) ``` #### Enterprise Edition Microsoft Azure ``` https://.valsight.eu/login/oauth2/code/openIdConnect https://-restore.valsight.eu/login/oauth2/code/openIdConnect (restore endpoint) ``` #### Enterprise Edition AWS ``` https://.valsight.app/login/oauth2/code/openIdConnect https://-restore.valsight.app/login/oauth2/code/openIdConnect (restore endpoint) ``` ## Group configuration To transfer groups in the OIDC Token, add the Optional Claim to the Token Configuration as shown in the screenshot. ![Bildschirmfoto 2025-12-09 um 11.14.49.png](./images/6520438797.png) ## Logout URL If desired, Valsight can redirect users to your logout URL after pressing the Logout Button in Valsight. Provide the URL to your contact in Valsight. By default, just the Valsight Session is logged out. --- # ENUM URL: https://docs.valsight.ai/enum/ Description: Iterates through the rows of the input and assigns a number to each row in ascending or descending order based on the magnitude of measures. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **ENUM** function **iterates through the rows of the input and assigns a number to each row in ascending or descending order** based on the magnitude of measures. Use this function when you need to assign sequential numbers (ranks) to rows based on their values, for example to build threshold rules or select the top/bottom N items. ## Syntax `ENUM('Node' [, "Order"])` ## Parameters | Parameter | Description | Type | Required | Default | | --------- | ------------------------------------------------------ | -------------- | -------- | ------- | | **Node** | An input node with rows to be enumerated. | Node reference | Yes | -- | | **Order** | Whether to enumerate in ascending or descending order. | Keyword | No | `"ASC"` | **Order options:** * `"ASC"`: The row with the smallest measure is assigned the number 1 and increases as the measures increase. This is the default. * `"DESC"`: The row with the largest measure value is assigned number 1 and increases as the measures decrease. ## Watch out * In case of rows having the same value, the tie breaking is done by looking at the **level values**. * The priority during tie breaking is determined by the **alphabetical order of the dimension names** and the hierarchy of levels within those dimensions. ## Examples ### Enumeration by measure value (ASC and DESC) This example shows how ENUM ranks rows by their values, first in ascending order (default), then in descending order. **Input node:** `'Node A'` | Year | Value | | ---- | ----- | | 2025 | 7 | | 2026 | 5 | | 2027 | 3 | | 2028 | -2 | **Formula:** `ENUM('Node A')` | Year | ENUM Result | | ---- | ----------- | | 2025 | 4 | | 2026 | 3 | | 2027 | 2 | | 2028 | 1 | **Formula:** `ENUM('Node A', "DESC")` Produces the enumerated result starting from the largest measure value. | Year | ENUM Result | | ---- | ----------- | | 2025 | 1 | | 2026 | 2 | | 2027 | 3 | | 2028 | 4 | ### Tie-breaking with multiple dimensions When rows share the same measure value, ENUM breaks ties using dimension levels in alphabetical order of dimension names and hierarchy within each dimension. **Dimensions & Levels:** Time → Year Product Dimension → Product Family, Product **Input node:** `'Node B'` | Year | Product Family | Product | Value | | ---- | -------------- | ----------- | ----- | | 2025 | Car | Big Car | 6 | | 2026 | Truck | Big Truck | -5 | | 2027 | Car | Small Car | -5 | | 2028 | Truck | Small Truck | 9 | **Formula:** `ENUM('Node B')` | Year | Product Family | Product | ENUM Result | | ---- | -------------- | ----------- | ----------- | | 2025 | Car | Big Car | 3 | | 2026 | Truck | Big Truck | 2 | | 2027 | Car | Small Car | 1 | | 2028 | Truck | Small Truck | 4 | In this case enumeration starts from the lowest measure, which is `-5`, where there is a tie on two rows. The function prioritises the Product dimension over `"Time"` since the name is alphabetically earlier. Within the product dimension, `"Product Family"` is the upper level in the hierarchy, so this level is used to break the tie, and the row with `"Car"` gets the first value over `"Truck"`. There is no other tie in the measures, so enumeration continues as usual for the rest of the rows. **Input node:** `'Node C'` | Year | Product Family | Product | Value | | ---- | -------------- | ----------- | ----- | | 2025 | Car | Big Car | -5 | | 2026 | Truck | Big Truck | -5 | | 2027 | Car | Small Car | -5 | | 2028 | Truck | Small Truck | -5 | | 2029 | Car | Small Car | -5 | **Formula:** `ENUM('Node C')` | Year | Product Family | Product | ENUM Result | | ---- | -------------- | ----------- | ----------- | | 2025 | Car | Big Car | 1 | | 2026 | Truck | Big Truck | 4 | | 2027 | Car | Small Car | 2 | | 2028 | Truck | Small Truck | 5 | | 2029 | Car | Small Car | 3 | In this more complex case every measure is equal. As mentioned in the previous example, the level `"Product Family"` is prioritised to break the tie; however, there is another tie as rows 1, 3, and 5 all share the same value `"Car"`. In this case the function looks at the next available level in the dimension, which is `"Product"`, and the row with `"Big Car"` is enumerated with value 1. Rows 3 and 5 still share the same value `"Small Car"`, so the function looks at the Time dimension `"Year"` to resolve the final conflict. ## Related | Function | When to use instead | | --------------------------- | ------------------------------------------------------------------------------------------------------------- | | [ENUM\_LEVEL](/enum-level/) | When you want to enumerate by the order of level values in dimension management rather than by measure value. | | [FINDFIRST](/findfirst/) | When you want to select one value per group rather than assign ranking numbers. | --- # ENUM_LEVEL URL: https://docs.valsight.ai/enum-level/ Description: Iterates through the values of the specified levels and returns each value with a number assigned in ascending or descending order according to the sequence in the dimension management. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **ENUM\_LEVEL** function **iterates through the values of the specified levels and returns each value with a number assigned in ascending or descending order** according to the sequence in the dimension management. Use this function when you need to number level values by their position in dimension management, for example to create index columns or define ordering rules independent of measure values. ## Syntax `ENUM_LEVEL("Level1" [, "Level2", ...] [, "Order"])` ## Parameters | Parameter | Description | Type | Required | Default | | --------- | -------------------------------------------------------------------------------------------------------- | ---------- | -------- | ------- | | **Level** | One or more levels whose values are enumerated, specified in double quotes (e.g. `"Year"`, `"Country"`). | Level name | Yes | -- | | **Order** | Whether to enumerate in ascending or descending order. | Keyword | No | `"ASC"` | **Order options:** * `"ASC"`: Enumerates in ascending order according to the sequence in dimension management. This is the default. * `"DESC"`: Enumerates in descending order (last value in dimension management gets number 1). ## Watch out * If multiple levels are passed to the function, the **alphabetical order of the dimension name** and the hierarchy of levels within that dimension will determine which level takes precedence in the event of a tie. ## Examples ### Enumeration along a single level (ASC and DESC) This example numbers each year value according to its position in dimension management, first ascending (default) then descending. **Formula:** `ENUM_LEVEL("Year")` | Year | ENUM\_LEVEL Result | | ---- | ------------------ | | 2025 | 1 | | 2026 | 2 | | 2027 | 3 | | 2028 | 4 | **Formula:** `ENUM_LEVEL("Year", "DESC")` | Year | ENUM\_LEVEL Result | | ---- | ------------------ | | 2025 | 4 | | 2026 | 3 | | 2027 | 2 | | 2028 | 1 | ### Enumeration across multiple levels When multiple levels are specified, the alphabetical order of dimension names determines which level takes precedence in the combined enumeration. **Dimensions:** Time → Year Location → Country **Formula:** `ENUM_LEVEL("Year", "Country")` | Year | Country | ENUM\_LEVEL Result | | ---- | ------- | ------------------ | | 2025 | France | 1 | | 2026 | France | 2 | | 2027 | France | 3 | | 2028 | France | 4 | | 2025 | Germany | 5 | | 2026 | Germany | 6 | | 2027 | Germany | 7 | | 2028 | Germany | 8 | In this example `"Location"` dimension is prioritised over `"Time"` which starts enumeration with rows having value `"France"` over `"Germany"`. Within the rows having same value, the `"Year"` level is used to further break the tie. ## Related | Function | When to use instead | | ------------------------ | ---------------------------------------------------------------------------------------------------- | | [ENUM](/enum/) | When you want to enumerate rows by measure value rather than by level order in dimension management. | | [FINDFIRST](/findfirst/) | When you want to select one value per group rather than assign ranking numbers. | --- # EQ (=) URL: https://docs.valsight.ai/eq/ Description: Checking whether matching rows are equal **Category:** [Logical functions](/logical-functions/) ## Overview The **EQ** function **compares the rows of two inputs** and returns true (1) if the values are equal and false (0) otherwise. Use this function when you need a 1/0 flag to mark matching values between two inputs. ## Syntax `EQ('Node1', 'Node2')` `'Node1' = 'Node2'` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | | **Node2** | Second input node. | Node reference | Yes | ## Examples ### Checking whether matching rows are equal This example compares two input nodes row by row. The result returns 1 where both values are equal and 0 where they differ. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 350 | | 2026 | 700 | | 2027 | 850 | | 2028 | 500 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 350 | | 2026 | 400 | | 2027 | 850 | | 2028 | 600 | **Formula:** `EQ('A', 'B')` | Year | EQ Result | | ---- | --------- | | 2025 | 1 | | 2026 | 0 | | 2027 | 1 | | 2028 | 0 | ## Related | Function | When to use instead | | ----------------- | -------------------------------------------------------------------------------------------------- | | [NEQ (!=)](/neq/) | When you want to mark mismatches instead of matching values between two inputs. | | [GT (>)](/gt/) | When you need to check whether one input is greater than another instead of checking for equality. | | [LT (<)](/lt/) | When you need to check whether one input is less than another instead of checking for equality. | --- # Example Excel Sheets URL: https://docs.valsight.ai/example-excel-sheets/ Description: Dimension Example 3 Demo Dimensions, one with a two-level hierarchy WARNING We do not longer recommend to use the “AUTO DIM” feature - please use the Valsi… | Name | Content | Link | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | Dimension Example | 3 Demo Dimensions, one with a two-level hierarchy **WARNING** We do not longer recommend to use the “AUTO DIM” feature - please use the Valsight Dimension Management instead. | [Dimension Example.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5094192317_Dimension-Example.xlsx) | | Regular Upload Sheet | One Sheet with 3 Levels and 2 Measures. Uses the dimension from the above example. | [Regular Upload.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5094192322_Regular-Upload.xlsx) | | 2D 3D 4D Upload Example | Various Multidimensional Upload Sheets. Uses the dimensions from the Dimension Upload Example. | [Multi-Dim Upload.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5094192312_Multi-Dim-Upload.xlsx) | --- # Excel upload feedback messages URL: https://docs.valsight.ai/excel-upload-feedback-messages/ Description: When uploading your Excel file to manage Dimensions, you may receive certain feedback messages on your file. When uploading your Excel file to manage Dimensions, you may receive certain feedback messages on your file. These can either be **informational messages** detailing what data would be updated if you proceed with uploading the file, or **error messages** denoting something is not right with the file and preventing it from being uploaded. This page explains in detail what these messages mean. ## Informational messages | Step | Detail | | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Uploading this Excel file will create these new values | **What happened**: Your new Excel file contains additional level values which will be added to your dimension.
**What you can do**: Check if the changes are the desired ones and confirm them.
![excel new values.png](./images/5094212440.png) ![new values v2.15.png](./images/5094212431.png) | | This Excel file doesn't add any new values to what you already have | **What happened**: Your new Excel file does not contain any new levels or level values compared to the old one.
**What you can do**: Make sure you select the correct, updated file. | | A level value has been moved to a different parent | **What happened**: A level value in your Excel file is mapped to a different parent than it currently has in the dimension. Uploading will move the value under the new parent in the hierarchy.
**What you can do**: Confirm the upload if the new parent assignment is the intended change. | | A level is being added or removed | **What happened**: Your Excel file adds a new level (column) to the dimension or removes an existing one. This changes the structure of the dimension itself, not just its values.
**What you can do**: Confirm the upload if the schema change is intended. | | Your Excel file has missing row(s) | **What happened**: Your Excel file is missing level values that exist in the current dimension. Valsight treats these as a request to delete those values when you confirm the upload. Depending on whether the values are used elsewhere, you will see **one of three outcomes**:
1. If the **values are not used anywhere**, the dialog shows a preview of the rows to be removed. Confirm to delete them. ![Bildschirmfoto 2026-05-20 um 11.17.23.png](./images/7001931822.png)
2. If the **values are referenced by data sources, nodes, line-items, charts**, the dialog lists them and warns that those references will no longer work after the upload. You can confirm anyway and clean up the references later, or cancel and restore the rows in your Excel file. ![Bildschirmfoto 2026-05-20 um 10.35.53.png](./images/7001931828.png)
3. If the **values are used as level links to another dimension**, the upload is blocked. Open the other dimension, remove the level links, and re-upload. You can also remove level values via [Dimension Management](https://wiki.valsight.com/x/XoHLAw). ![Bildschirmfoto 2026-05-20 um 10.38.47.png](./images/7001931834.png) | ## Errors The dialog distinguishes messages that **block** the upload from those that only warn you. Anything below stops the upload until you fix the file. The messages here are the ones a normal dimension upload produces; a dimension that carries [labels](/linked-levels/) can raise a few more about attribute columns and links. Whichever message you get, it names the sheet, column or value at fault, so read that part before changing the file. | Step | Detail | | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Your Excel file has duplicate row(s) | **What is wrong**: Two or more rows in the dimension table are identical. Every row needs to be unique.
**What you can do**: Remove the duplicate rows from your Excel file and upload it again. The error message indicates which rows are duplicated. | | Your Excel file has ambiguous mapping(s) | **What is wrong**: The Excel file contains level values that map to more than one parent value.
**What you can do**: Make sure your Excel file follows the structural guidelines for dimensions in Valsight ([Creating Dimensions](/creating-maintaining-dimensions/)). Most importantly, every level value needs to be uniquely mapped to a single parent level.
![excel ambiguous values.png](./images/5094213031.png) ![ambiguous values v2.15.png](./images/5094213416.png) | | Your Excel file has missing column(s) | **What is wrong**: The number of columns in the Excel file you are trying to upload is lower than the number of levels in that particular dimension. The number of columns needs to match the number of levels in any given dimension.
**What you can do**: The error message you received should also denote which columns are missing. Please ensure those columns are present in your Excel file, then upload it again.
![Excel missing columns.png](./images/5094212337.png) ![missing columns v2.15.png](./images/5094212342.png) | | Missing sheets(s) | **What is wrong**: A worksheet the dimension expects is not in your file. Sheets are matched by **name**, not by count, so a file with the right number of sheets still fails if one has been renamed.
**What you can do**: The message lists the names it could not find. Rename your worksheets to match them, then upload again.
![excel #worksheet.png](./images/5094212881.png) | | Invalid sheets(s) | **What is wrong**: Your file contains a worksheet the dimension does not expect. The message lists the names.
**What you can do**: Remove the extra worksheets, rename them to the expected names, or write a `#` in front of their names so Valsight ignores them. | | Your Excel file has duplicate column(s) | **What is wrong**: Two columns in a sheet carry the same header, so Valsight cannot tell which level a value belongs to.
**What you can do**: Rename or remove the duplicate column and upload again. | | Level(s) in use | **What is wrong**: Your file removes a level that something in the project still uses.
**What you can do**: The message lists what uses it. Clear those references first, or put the level back into your file. | | Some row(s) have undefined values | **What is wrong**: A row leaves a cell empty. Every row needs a value on every level.
**What you can do**: Fill the empty cells, or delete the incomplete rows, and upload again. | | Sheet contains unrecognized columns | **What is wrong**: A sheet holds a column that matches no level or label of the dimension.
**What you can do**: Rename it to the expected name, remove it, or write a `#` in front of the header so Valsight ignores it. | | Undefined attribute values | **What is wrong**: A [label](/linked-levels/) column is missing values for some rows.
**What you can do**: Fill them in, or remove the label column from the sheet if you do not want to update it. | | Your Excel file is too big for the upload | **What is wrong**: The Excel file is larger than the allowed size limit (e.g. 20mb).
![Screenshot 2020-08-07 at 10.21.59.png](./images/5094219085.png) | --- # Excel upload of Assumptions & Line-Items URL: https://docs.valsight.ai/excel-upload-of-assumptions-line-items/ Description: You can download all data of an Assumption as an Excel file with one sheet per Line-Item. You can edit the data and upload the file to the same Assumption ag… You can download all data of an Assumption as an Excel file with one sheet per Line-Item. You can edit the data and upload the file to the same Assumption again. **Download Excel** is a submenu with two options, and the choice decides whether the file round-trips: * **Line-Items in "All Details" view** is the raw per-line-item data table. Download this one when you intend to edit the file and upload it again. * **Line-Items in their current view** reflects the active filters and the chosen Change, Result or Absolute columns. It is a report, not a re-uploadable source. > **An upload replaces the data, it does not merge into it.** Rows that exist in the line-item but are missing from the file you upload are removed. Every sheet in the file must map to a line-item variant, or the upload fails with ‘Sheet does not match any assumption’, and every variant must have a sheet, or it fails with ‘Uploaded XLSX file is missing sheets for assumptions’. Partial uploads are rejected. In some cases you want to upload the data to new or other Assumptions, either in the same or other workspaces. Refer to the following tables about supported use cases: | Task | Supported | | ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Creating your own Excel file in the same structure | Yes, the system matches the Sheet and Assumption Line-Item name. A leading `(1.1) ` index, which downloaded files carry, is stripped before comparing, so `(1.1) My line-item` and `My line-item` both match. Beyond that the sheet name must match exactly, and Excel caps sheet names at 31 characters, so a long line-item name is truncated on download and has to be reproduced truncated. | | Uploading the downloaded Excel Sheet to another Assumption with the same structure (for example a duplicated Assumption) | Only if the file has no `Metadata` sheet. With one, line-items are matched by their UUID, and a duplicated assumption gets fresh UUIDs, so the upload fails with ‘Line-item with uuid … not found.’ rather than matching by sheet name. Works for a single line-item with one unfiltered variant, or after deleting the `Metadata` sheet from the file. | | Filling in the data of a downloaded file via formulas | Yes | | Changing Level Values to existing Level Values | Yes, if they are included in the Assumption Line-Item Filter | | Having additional Sheets in the upload file | Yes, but they must start with the number symbol (#) | > **Uploading all assumptions at once takes a ZIP file.** The single-assumption upload accepts `.xlsx` and `.xlsm`. The workspace-wide upload, reached from the import and export menu of the Scenario Manager, accepts only a `.zip` archive holding those Excel files; its dialog is titled ‘Upload All Excel Files as a Single ZIP File’. ## The Metadata sheet Most downloads carry an extra first sheet named `Metadata`. Each of its rows gives a **Line-item name**, a **Line-item UUID**, a **Variant name** and the **Sheet** they belong to, and that is what an upload uses to put every sheet back where it came from. Keep the sheet in the file, and keep those four columns: a missing one is rejected with ‘The ‘Metadata’ is missing the mandatory column ‘…’.’ Valsight adds the sheet whenever the assumption has more than one line-item, more than one variant, or a filtered or non-default view, and always for a workspace-wide download. Only the simplest case, a single line-item with one unfiltered variant, comes without one. > The sheet is not required on upload. Without it, Valsight falls back to matching sheets by name, which is what the table above describes. ## Data format ### Time in rows Use a standard upload format with years in rows for your Assumptions. | Country | City | Year | Change | | ------- | ------ | ---- | ------ | | USA | Boston | 2021 | 100 | | Germany | Berlin | 2021 | 200 | | USA | Boston | 2022 | 300 | | Germany | Berlin | 2022 | 600 | | USA | Boston | 2023 | 500 | | Germany | Berlin | 2023 | 1000 | ## Time in columns Use an upload format with years in columns. Tables like this are typically used in financial data tables. | Country | City | 2021 | 2022 | 2023 | | ------- | ------ | ---- | ---- | ---- | | USA | Boston | 100 | 300 | 500 | | Germany | Berlin | 200 | 600 | 1000 | Correct data upload for years in columns. | Engine | 2020 | 2021 | 2022 | 2023 | | ---------- | ---- | ---- | ---- | ---- | | Jet engine | 1 | 1 | 1 | 1 | | Ottomotor | 1 | 1 | 1 | 1 | ## Possible error messages when uploading data **Error message:** *"Parameter Table must contain exactly one measure column, but contains: '\[Paris, Augsburg, Berlin, Hannover]'"* **Error:** When this error message appears, a different level than time has been used in columns (horizontally). **Example:** | Year | Paris | Berlin | Munich | Hamburg | | ---- | ----- | ------ | ------ | ------- | | 2020 | 12 | 12 | 12 | 12 | | 2021 | 12 | 12 | 12 | 12 | | 2022 | 12 | 12 | 12 | 12 | **Error message:** *"Parameter table must contain exactly one measure column, but contains: "\[]"* **Error:** When this error message appears, a merged column has been used as highest column horizontally. **Example:**

2020

2020-Q1

2020-Q2

2020-Q3

2020-Q4

1

1

1

1

1

1

1

1

**Error message:** *"Column '2020.0' could not be identified. Use a level name or Measure/Change or Comment."* **Error:** When this error message appears, either data is uploaded into a year that is not within the project horizon or the uploaded excel contains multiple (time) levels as column headers. **Examples:** | 2020 | | | | 2021 | | | | | ------- | ------- | ------- | ------- | ------- | -------- | ------- | ------- | | 2020-Q1 | 2020-Q2 | 2020-Q3 | 2020-Q4 | 2021-Q1 | 20201-Q2 | 2021-Q3 | 2021-Q4 | | 12 | 12 | 12 | 0 | 0 | 0 | 0 | 0 |

2020

2020-Q1

2020-Q2

2020-Q3

2020-Q4

1

1

1

1

1

1

1

1

**Error message:** *"Missing data on 'City' levels 'Profit' which are required by Assumption '{2}' / New parameter data contains duplicate values for '\[2020]'"* **Error:** When this error appears, the uploaded Excel file is missing a column header for a level. **Example:** | | 2020 | 2021 | 2022 | 2023 | | ------- | ---- | ---- | ---- | ---- | | Paris | 12 | 12 | 12 | 12 | | Berlin | 12 | 12 | 12 | 12 | | Munich | 12 | 12 | 12 | 12 | | Hamburg | 12 | 12 | 12 | 12 | > **Not supported uploads** > > Uploading Excel Sheets with merged cells within the data is not supported and an error message will appear. > > The download you edit and send back is normally the change view, so upload changes rather than target values. Uploading target values is possible, but only if the `Metadata` row for that sheet sets its view to the result view **and** names the scenario the values apply to. Get either half wrong and the upload is rejected with a message telling you which. > > Tables may only contain upper case letters (e.g. 2021-Q1 instead of 2021-q1) --- # EXP URL: https://docs.valsight.ai/exp/ Description: Returns Euler's number, e (~2.718) raised to a power of the given value, while retaining all dimensions. Use this when you need to compute e raised to the power of node values, for example in continuous growth or compounding models. **Category:** [Math & numeric](/math-numeric/) ## Overview The **EXP** function **returns Euler's number, e (\~2.718) raised to a power of the given value**, while retaining all dimensions. Use this function when you need to compute e raised to the power of node values, for example in continuous growth or compounding models. ## Syntax `EXP('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | ## Examples ### Exponential transformation of node values This example computes e raised to the power of each value in the input node. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 3 | | 2027 | 4.5 | **Formula:** `EXP('A')` | Year | EXP Result | | ---- | ---------- | | 2025 | 7.39 | | 2026 | 20.09 | | 2027 | 90.02 | ## Related | Function | When to use instead | | ---------------- | -------------------------------------------------------------------------- | | [LN](/ln/) | When you need the natural logarithm (inverse of EXP). | | [LOG](/log/) | When you need a logarithm with a specific base. | | [POWER](/power/) | When you need to raise values to an arbitrary exponent rather than base e. | --- # EXPAND URL: https://docs.valsight.ai/expand/ Description: The EXPAND function creates a full cross product of existing rows with all values of specified levels, used to initialize empty data rooms or add dimensions to nodes. **Category:** [Dimensionality & hierarchies](/dimensionality-hierarchies/) ## Overview The **EXPAND** function **expands a node** by creating a full cross product of all existing rows **with all values** **of the specified level(s).** Use this function when you need to create an empty data room (a set of rows with placeholder values) that can serve as a driver inside [ROLLFORWARD\_ADVANCED](/rollforward-advanced/), or when you want to expand an existing node with additional levels. ## Syntax `EXPAND('Node', "Level1" [, "Level2", ...])` **Example usage:** `EXPAND('Growth Rate', "Product")` ## Parameters | Parameter | Description | Type | Required | | ----------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------ | -------- | | **Node** | Input node or scalar value, specified in single quotes (e.g. `'Growth Rate'`) or as a number (e.g. `0`) | Node reference or number | Yes | | **Level1, Level2, ...** | Level names to expand, specified in double quotes (e.g. `"Product"`) | Level name | Yes | ## Output shape | Aspect | Behavior | | -------------- | --------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Adds the specified levels (and their upper levels in the dimension hierarchy) to the result | | Values | Existing values are duplicated across all members of the new level(s). Scalar inputs fill every cell with that value. | | Row count | Full cross product | ## Watch out * EXPAND creates the **full cross product of all values in the specified level(s)**. If you only need specific values, use EXPANDSINGLE instead. * Expanding a node copies each row's value into every member of the new level. Be aware this **changes totals**. For example, if a row has value 100 and you expand across 3 products, the sum becomes 300 instead of 100. ## Examples ### Expand a scalar to full dimensionality Initialize an empty simulation node with zeros across all years, regions, and products. **Formula:** `EXPAND(0, "Year", "Region", "Product")` | Year | Region | Product | EXPAND Result | | ---- | ------ | ------- | ------------- | | 2025 | EMEA | Alpha | 0 | | 2025 | EMEA | Beta | 0 | | 2025 | APAC | Alpha | 0 | | 2025 | APAC | Beta | 0 | | 2026 | EMEA | Alpha | 0 | | ... | ... | ... | ... | The scalar `0` is replicated across every combination of Year × Region × Product. The result makes the simulation node eligible for use with ROLLFORWARD. ### Expand a node to add a dimension A growth-rate node only has a Year level, but should also include the Product level. **Input node:** `'Growth Rate'` | Year | Value | | ---- | ----- | | 2025 | 0.03 | | 2026 | 0.05 | **Formula:** `EXPAND('Growth Rate', "Product")` | Year | Product | EXPAND Result | | ---- | ------- | ------------- | | 2025 | Alpha | 0.03 | | 2025 | Beta | 0.03 | | 2026 | Alpha | 0.05 | | 2026 | Beta | 0.05 | The same growth rate per year is now available for each product. ### Expand into a finer level within an existing dimension A revenue node already has a `"Region"` level. You want to break it down to individual countries, a finer level in the same dimension hierarchy. **Input node:** `'Revenue Target'` | Year | Region | Value | | --------- | ------ | ------- | | 2025 | EMEA | 500 | | 2025 | APAC | 300 | | **Total** | | **800** | **Formula:** `EXPAND('Revenue Target', "Country")` | Year | Region | Country | EXPAND Result | | --------- | ------ | --------- | ------------- | | 2025 | EMEA | Germany | 500 | | 2025 | EMEA | France | 500 | | 2025 | APAC | Japan | 300 | | 2025 | APAC | Australia | 300 | | **Total** | | | **1600** | Because `"Country"` is a finer level below `"Region"` in the hierarchy, EXPAND adds only the child values belonging to each region, not a full cross product of all countries with all regions. Note that the values are duplicated into each child row, so totals will increase. ## Related | Function | When to use instead | | ----------------------------------------------- | ------------------------------------------------------------------------- | | [EXPANDSINGLE](/expandsingle/) | When you only need specific level values instead of a full cross product. | | [DROPLEVEL](/droplevel/) | When you need to remove levels instead of adding them. | | [ROLLUP](/rollup/) | When you want to aggregate to fewer levels. | | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) | When you need to project expanded driver nodes forward in time. | --- # EXPANDSINGLE URL: https://docs.valsight.ai/expandsingle/ Description: The EXPANDSINGLE function expands a node by adding specific level values for one or more levels. **Category:** [Dimensionality & hierarchies](/dimensionality-hierarchies/) ## Overview The **EXPANDSINGLE** function **expands a node** **by adding specific** **level values** for one or more levels. For each specified level-value pair, the function creates rows containing the value from the input node. Use this function when you want to assign a value to a specific dimensional combination, such as creating entries for a particular year, region, or product. ## Syntax `EXPANDSINGLE('Node', "Level1", Value1 [, "Level2", Value2, ...])` **Example usage:** `EXPANDSINGLE('Sales', "Year", "2025")` ## Parameters | Parameter | Description | Type | Required | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | -------- | | **Node** | Input node, specified in single quotes (e.g. `'Sales'`) | Node reference | Yes | | **Level1, Level2, …** | Level on which the node should be expanded, specified in double quotes (e.g. `"Year"`) | Level name | Yes | | **Value1, Value2, …** | Level value used for expansion, specified in double quotes. Can be a single value or a list of values (e.g. `"2025"` or `["2025", "2026"]`) | Level value / Level value list | Yes | Multiple Level–Value pairs can be provided to expand across multiple dimensions. ## Output shape | Aspect | Behavior | | -------------- | ----------------------------------------------------- | | Dimensionality | Adds the specified level(s) to the result | | Values | Each created row contains the value of the input node | | Row count | One row per specified level-value combination | ## Watch out * Unlike EXPAND, EXPANDSINGLE creates rows only for the **explicitly specified level values**, not for the full cross product. * The specified level values must exist in the hierarchy. * When a list of values is provided, one row is created for each value. * You cannot expand on a level whose dimension already exists on the input node at the same or coarser granularity. You can only expand by a more fine-grained level in that dimension. ## Examples ### Expand a value to a specific year **Input node:** `'Node'` | Value | | ----- | | 1.1 | **Formula:** `EXPANDSINGLE('Node', "Year", "2026")` | Year | EXPANDSINGLE Result | | ---- | ------------------- | | 2026 | 1.1 | The value is assigned to the Year 2026. ### Expand across multiple levels **Formula:** `EXPANDSINGLE('Node', "Year", "2026", "Product Group", "Cars")` | Year | Product Group | EXPANDSINGLE Result | | ---- | ------------- | ------------------- | | 2026 | Cars | 1.1 | The value is expanded across two dimensions simultaneously. ### Expanding to multiple values You can also provide a list of values. **Formula:** `EXPANDSINGLE('Node', "Year", "2026", "Product Group", ["Cars", "Trucks"])` | Year | Product Group | EXPANDSINGLE Result | | ---- | ------------- | ------------------- | | 2026 | Cars | 1.1 | | 2026 | Trucks | 1.1 | Each value in the list creates a new row. ### One-time tax relief in 2026 **Input node:** `'Base Taxation'` | Year | Value | | ---- | ----- | | 2025 | 1,000 | | 2026 | 1,000 | | 2027 | 1,000 | | 2028 | 1,000 | **Input node:** `'Relief Value'` | Value | | ----- | | 500 | **Formula:** `EXPANDSINGLE('Relief Value', "Year", "2026")` **Output node:** `'Relief Expanded'` | Year | EXPANDSINGLE Result | | ---- | ------------------- | | 2026 | 500 | **Calculation:** `'Base Taxation' - 'Relief Expanded'` | Year | Value | | ---- | ----- | | 2025 | 1,000 | | 2026 | 500 | | 2027 | 1,000 | | 2028 | 1,000 | The relief only affects 2026, because that is the only expanded year. ### Example with hierarchical levels If a hierarchy exists, specifying the **lowest level** is sufficient. **Example hierarchy** Product Group → Product Line → Product **Input node:** `'Quantity'` | Value | | ----- | | 500 | **Formula:** `EXPANDSINGLE('Quantity', "Product", "Max T 3")` | Product Group | Product Line | Product | EXPANDSINGLE Result | | ------------- | ------------ | ------- | ------------------- | | Cars | Sedans | Max T 3 | 500 | Because "Max T 3" belongs to the product line "Sedans," which in turn belongs to the product group "Cars," Valsight automatically fills in these parent levels in the result. You only need to specify the most detailed level. ### Using a project variable as the level value Instead of hardcoding a year, you can use a project variable so the formula updates automatically when the variable changes. **Formula:** `EXPANDSINGLE('Relief Value', "Year", "$PLANNING_START")` This creates a row for the year currently defined by `$PLANNING_START`, no formula change needed when the planning horizon shifts. **See also:** [Project Variables](/project-variables/) ## Related | Function | When to use instead | | ------------------ | ------------------------------------------------------------------------------------------- | | [EXPAND](/expand/) | Expands nodes by creating rows for every possible combination of the specified level values | | [FILTER](/filter/) | Restricts rows instead of expanding them | --- # Expected Levels URL: https://docs.valsight.ai/expected-levels/ Description: Expected levels define the minimum dimensional shape for a node, allowing empty nodes to pass model validation and serve as blueprints for simulation. Expected levels define the **minimum dimensional shape** for a node, allowing **empty nodes** to pass model validation and serve as **blueprints** for simulation. ## When to use it * When setting up simulation blueprints that will later be populated with line-item data * When empty placeholder nodes should not block model validation * When you want to document the intended shape of a node before its logic is fully defined ## How it works When you assign expected levels to a node, the system treats the node as if those dimensions are present. This means: * The node passes model validation even without data * Other nodes that reference it can resolve level expectations * The node is ready to receive line-item data in simulations Expected levels are a minimum-granularity contract rather than a pure placeholder, so they keep being checked once the node does produce data. Model validation then warns when the real levels do not hold up: * The level the node actually produces for a dimension is **coarser** than the expected one * An expected dimension is **absent from the node** altogether * An expected level has since been **deleted** from its dimension > **Clear expected levels once the node has a formula of its own.** They are not switched off when the node is populated, so entries left over from the blueprint stage turn into validation warnings on a node that is otherwise finished. ## Steps ### Identify the empty node Select the node on the canvas. Without a formula, the node has no available levels. ![image-20260402-093505.png](./images/6861783078.png) ### Open the validation settings In the **Node Editor** (right-side Context Panel), open the **Validation Settings** tab. ### Add expected levels Add all levels the node should have in the future under **Expected Levels**. ![image-20260402-093611.png](./images/6862209038.png) ### Save and verify After saving, the node displays the chosen levels as available levels and passes model validation. ![image-20260402-093635.png](./images/6862569497.png) ## FAQ **Does setting expected levels add actual data to the node?** No. Expected levels only declare the dimensional shape. The node remains empty until data or a formula is assigned. **Can I change expected levels later?** Yes. Update them at any time through the Validation Settings tab in the editor. **When should I use expected levels instead of a formula?** Use expected levels when the node is intentionally empty (e.g. a simulation blueprint). Use a formula when the node should calculate or reference data. ## Related * [Validation Nodes](/validation-nodes/): define custom conditions that check model results * [Model Validation](/model-validation/): how model validation uses expected levels * [Nodes](/nodes/): overview of node types and behavior --- # Export Control Classification Number URL: https://docs.valsight.ai/export-control-classification-number/ Description: ECCNs are five character alphanumeric designations used on the Commerce Control List (CCL) to identify dual-use items for export control purposes. An ECCN c… ECCNs are five character alphanumeric designations used on the Commerce Control List (CCL) to identify dual-use items for export control purposes. An ECCN categorizes items based on the nature of the product, i.e. type of commodity, software, or technology and its respective technical parameters. > The Valsight Simulation Platform is developed entirely in Germany and includes a variety of third-party and open-source components. While some of these components originate from U.S. sources, they are classified as EAR99 and are not subject to specific export restrictions. The platform does not include any controlled U.S. technology that would exceed the 25% de minimis threshold defined under the U.S. Export Administration Regulations (EAR). **Therefore, the software is not subject to the EAR** and thus, does not have an ECCN. --- # Export Formats URL: https://docs.valsight.ai/export-formats/ Description: With the introduction of the Export Manager it is now possible to version your exports as well as the OData Link. An OData Link can be used to either import … With the introduction of the Export Manager it is now possible to version your exports as well as the OData Link. An OData Link can be used to either import versioned data of an export or create a connection to a Valsight export which will re-upload the most recent version of an export whenever a new version is triggered. ## Available export formats ### 1. Excel ### 2. CSV ### 3. OData **3a.** **Live Link** **3b. Versioned Link** **3c. Specific Link** **3d. Old Link** ## Export format description ### 1. Excel Downloads the nodes with the selected scenario context as a XLSX file, where every node is a separate tab of the file. The first tab is not a node: it holds the export's metadata and is the one open when you first open the file. A node using RATIO adds one or two extra tabs of its own. ### 2. CSV Downloads the nodes with the selected scenario context as a CSV. The file is UTF-8, comma-separated, and uses the point as its decimal separator with no thousands grouping, whichever locale you work in. On a German system that means opening it through Excel's text import rather than by double-clicking it. Cells that would otherwise look like a formula to Excel are prefixed so that spreadsheet software treats them as text. ### 3. OData #### 3a. Live link > Recommended if you want to have a fully live connection between the scenario in Valsight and wherever the OData link is called from. Especially useful for connecting to an external database. To create a link to an export that is constantly synchronised with the data in Valsight, create a link to the export itself in the Export Overview. Simply browse or navigate to the desired export and click the download button. Select the 'OData-live' option and copy the link. ![image-20240611-090252.png](./images/5566103566.png) *Any changes made in Valsight will be synchronised immediately.* #### 3b. Versioned link > Recommended if you wish to import the latest version of the export, only when a new version is available in Valsight. To generate a link to an export which will continuously update to the most recent export version available in Valsight, generate a link on the export itself in the export overview. Simply search for or navigate to your desired export and click on the download button. Select “OData-**version**” as the option and copy the Link. This link can now be used in external software to pull the latest version of this specific export, whenever a new version is created. ![image-20240611-090230.png](./images/5566169093.png) *If the latest version failed to export, the OData link will still work and import the latest successful version. This is to ensure no external models will break if an export failed for an unexpected reason.* #### 3c. Specific link > Recommended if you only wish to import data once. To import a specific version of an export please navigate to the export version history page by clicking on the exports name. Select the desired version manually or by searching for the name, description, date created or the user which created the version. To get the OData link, click on the three-dot menu on the right of the selected version and select “Download as OData”. Copy the link and use it wherever you wish to import the data. As the version is saved, you can reuse the same link in different places to pull this specific version. ![image-20240405-153252.png](./images/5459017750.png) *This OData link will not receive any newer versions and is not suitable if you wish to update data.* #### 3d. Old link *For links generated before the column order was standardized.* These links act like the new ‘Live links'. Supported indefinitely. ### Export formatting The column order is predictable: it no longer depends on the levels or on the node operations, so it does not change when a node operation is altered. The structure is: 1. **Standard Column Order:** A CSV starts with ‘Scenario’, ‘Model’ and ‘Node’. An OData export starts with ‘RowNumber’, which is its row key, followed by the same three. 2. **Dimension Grouping:** Levels are grouped by dimension and sorted alphabetically. 3. **Level Sorting:** Within each dimension, levels with the same name are organized from top to bottom (e.g., Year, Quarter, Month). 4. **Measure Placement:** Measure is consistently positioned at the end. This way, an exports column order can no longer randomly changed because a node operation was altered. This applies to both standard and OData scenario exports. If you have older reports built on the previous, unpredictable column order, update them to match. ## Related * [Export Manager](/export-manager/) --- # Export Manager URL: https://docs.valsight.ai/export-manager/ Description: See below a brief overview over the key functions of the Export Manager. To learn more about a specific functionality, simply navigate to the sub-page. The Export Manager is where you export scenarios, manage their versions, and share exports with other projects. Users with write access to the project can also create templates and manage the team's exports. > **Export storage is capped per instance.** The header shows how much is left, as ‘Export Manager storage: … free of …’. An export that would take you over the limit is aborted, and you are told the maximum has been reached. Delete exports or versions you no longer need to free space, remembering that exports saved indefinitely never expire on their own. ## Navigating the Export Manager See below a brief overview over the key functions of the Export Manager. To learn more about a specific functionality, simply navigate to the sub-page. ![Group 12.png](./images/5565480969.png) ### 1. Accessing the Export Manager Access the Export Manager through the Icon (1) on the left navigation bar. The Export Manager allows you to export Scenarios, view your exports, download and share them with other projects or manager them. Non-admins can manage their own exports and downloads whilst admins can view and manage the exports of their team. ![image-20240604-082954.png](./images/5551915013.png) ### 2. Template Manager You can navigate between two tabs (2) within the Export Manager: “Exports” and “Templates”. “Exports” will present you with a list of all available exports, the possibility of creating a new export as well as managing, sharing or downloading existing exports. The “Template Manager” needs write access to the project. It allows for the creating of templates for multiple use cases, for example later exports by preselecting nodes and reusing this constellation at multiple occasions. For more information regarding the Template Manager please read [**here**](/template-manager/). ![image-20240604-082912.png](./images/5551521810.png) ### 3. Creating an export To [**create an export**](/creating-and-downloading-an-export/) in the Export Manager, click on the ‘Create Export’ button on the top right (3). This will open a dialogue in which you can chose a model, scenario and nodes to export. Alternatively, you can also create an export directly in the Scenario Manager. This will calculate and create the export and save it in the Export Manager for further use. Note that this process might take a while depending on the size of the nodes. You can continue working elsewhere ,as the export is being created in the background. Once the export is done you will be notified via the green message in the top of the screen. Click on ‘View’ to get to the Export Manager and download the export. ![image-20240604-082842.png](./images/5551620104.png) ### 4. Downloading exports You can download or share the latest version of an export in various [**formats**](/export-formats/)**.** It is possible to download them or create links to the export, either to a specific, the latest or a live version. To do so, you can navigate to the download button on the right of each export or directly in the callout message after creating a new export. Select the desired format and the export will be downloaded. Note, that if the latest version failed, the download button will be disabled. Either create a new version or delete the failed one. ![image-20240611-091042.png](./images/5566005298.png) ### 5. Managing exports Through the export's three-dot menu, you can create a new version of the export, delete it, or edit it. ![image-20240604-082714.png](./images/5551947804.png) [**Editable features**](/managing-exports/) are: ‘Shared projects’, ‘Export Expiration Date’, ‘Name’ and ‘Description’. > Deleting an export will delete all its underlying versions. Projects with access to these versions will no longer be able to import them. However, if a project has already imported this export, the Data Source will **not** be deleted. ### 6. Sharing exports A key functionality of the Export Manager is the ability to [**share exports**](/sharing-exports/) with other projects. To do this you can either select the option directly in the creating export dialogue or allow this at a later stage through export settings. To share, check the box “share with other projects” and select the desired projects from the list of available projects to you. Once created, users from the destination project will be able to import the scenario export as a new Data Source just like they would import any other Data Source through the tab “From another project. ![image-20240604-083250.png](./images/5552406536.png) > You can share exports on a per-export level with other project. This will allow these projects to import any current and future version of this export unless access is revoked. ### 7. Versioning The Export Manager allows you to [**version your exports**](/versioning-of-exports/) as well as view an exports version history. When creating the first export for a scenario, a first version is automatically created. The export and its versions share the given name, which can be changed at any time to a custom or different name. You can create a new version of an export at any time on an available export from within the Export Manager. Simply click on the three-dot menu of an export and click “Create new Version”. If no custom name is assigned, a custom name will be generated. It is recommended to add additional information about the version in the description. ![image-20240604-082656.png](./images/5551947798.png) > To view the versions of an export simply click on an export to view the version history page. Here you can see a list of all available versions of an export, as well as delete and download them through the three-dot menu. ### 8. Navigating the Export Manager There are multiple tools which help you navigate and manage your exports faster and simpler. Apart of the search bar, which allows you to search for an exports name, description or creation date, you can filter your export list with the quick filters ‘saved’ and ‘shared’. These filter the list for all exports which are saved indefinitely and shared with other projects respectively. ![image-20240604-083644.png](./images/5552209939.png) --- # External Data Source Connections (ODATA / JDBC) URL: https://docs.valsight.ai/external-data-source-connections-odata-jdbc/ Description: You can create data sources with connections to external systems. Supported are connections via ODATA and JDBC. Besides uploaded XLSX files, the data source type dropdown offers three connections to external systems: **OData**, **JDBC** and **CSV URL Download**. On instances where export sharing is licensed and switched on, **External Project** appears as a fifth type (see [Sharing exports](/sharing-exports/)). * **Name:** The internalname of the database that should be created. * **URL:** Enter the ODATA service root URL or JDBC URL, e.g. or jdbc\:postgresql://localhost:5432/DB\_NAME * Authentication for OData and JDBC is performed via **username** and **password**. The checkbox **Always require users to enter password** is ticked by default, and while it is ticked the password is discarded after the import and has to be entered again on every re-import. Untick it to have the password stored encrypted in the application database. * **Tables to import:** You can limit the scope of the import by providing a comma separated list of tables. Removing a table from the list will not delete the table. If empty, all accessible tables will be imported. * On successful creation, the system will import the tables to the system. They can then be accessed as any other data source via the DATA function in models. If needed, a re-import can be triggered using "**Re-Import Tables".** ## ODATA connections To connect to a system using ODATA, navigate to the data source page in your project and create a new data source with the type *OData*. ![Screenshot 2020-04-03 at 15.23.30.png](./images/5094190989.png) Supported versions: * ODATA V2 ## JDBC connections To connect to a system using JDBC, navigate to the data source page in your project and create a new data source with the type *JDBC*. ![Screenshot 2020-04-03 at 15.30.44.png](./images/5094190994.png) These databases are supported, each with the shape of JDBC URL it expects: | Database | JDBC URL | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | PostgreSQL | `jdbc:postgresql://:5432/?currentSchema=` | | SQL Server | `jdbc:sqlserver://:1433;databaseName=` | | MariaDB | `jdbc:mariadb://:3306/` | | Snowflake | `jdbc:snowflake://.snowflakecomputing.com/?warehouse=&db=&schema=&role=` | For Snowflake, give all four of `warehouse`, `db`, `schema` and `role`. The warehouse runs the queries, the role decides which objects are visible at all, and naming the schema is what puts the connection in the schema your tables and views actually live in. Treat `schema` as required rather than optional. Pick the database from the dropdown in the data source form and it fills in the matching URL template for you. The choice itself is not stored: the URL stays the single source of truth, so correcting the URL later is all it takes to point a data source at a different database. ### Snowflake key-pair authentication A Snowflake data source can authenticate with a **key pair** instead of a password. Every other database authenticates with a username and password. Snowflake is retiring password authentication for service users, so on accounts where that enforcement already applies, key-pair authentication is the only way to connect. Select the key-pair method in the data source form and upload the private key together with the rest of the connection configuration. The key must meet these requirements: | Requirement | Value | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | Algorithm | RSA | | Minimum key length | 2048 bits | | Accepted formats | PKCS#8 PEM, encrypted or unencrypted, which is the `.p8` file Snowflake's own instructions produce; PKCS#1 PEM; raw PKCS#8 DER | | Passphrase | Needed only for an encrypted key. It is used once to read the key and is never stored. | The key is stored encrypted in the application database, the same way a saved password is. To rotate a key, upload the replacement on the data source's edit screen. ### Tables to import ## CSV URL Download A CSV URL Download data source fetches a CSV file from a URL instead of querying a database. It has no username and password. In their place it offers an **Authentication Type** selector, set either to no authentication or to one of the OAuth providers configured on the instance (see [OAuth 2.0 for URL external data source authentication configuration](/oauth-2-0-for-url-external-data-source-authentication-configuration/)). ## Notes on tables to import **Tables to import** must be in the default schema of the user. Otherwise the import will fail as it does not find the respective tables. If left empty, the user must only see one schema and this must be the user's default or connection's default. On Snowflake, Valsight lists only the tables and views in the database and schema that the connection itself reports. Snowflake otherwise reports every schema of the account, including objects that cannot be imported at all, because tables are read unqualified. If the JDBC URL does not name a schema, the connection lands in whatever default schema the account gives it, and anything outside that schema is simply absent from the list. Nothing reports why, so the symptom is a table or view you know exists that Valsight cannot find. Adding `schema=` to the URL and re-importing is the fix. This narrowing applies to Snowflake only. Every other database is unchanged, because PostgreSQL and SQL Server resolve unqualified names through a search path that may name several schemas, and scoping there would hide tables that import perfectly well. --- # FACT URL: https://docs.valsight.ai/fact/ Description: This example computes the factorial of each value in the input node. **Category:** [Math & numeric](/math-numeric/) ## Overview The **FACT** function **returns the factorial of a number**. The factorial of a number is equal to 1×2×3×...×number. Use this function when you need to compute the factorial of node values, for example in combinatorial calculations or probability models. ## Syntax `FACT('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | ------------------------------------------------- | -------------- | -------- | | **Node** | An input node with values to calculate factorial. | Node reference | Yes | ## Watch out * Factorial cannot be computed on **negative numbers**. * The input cannot contain **numbers larger than 20**. * Any **decimal number** will be rounded to the smallest value, e.g. 3.725 → 3. ## Examples ### Factorial of integer values This example computes the factorial of each value in the input node. **Input node:** `'Node'` | Year | Value | | ---- | ----- | | 2025 | 0 | | 2026 | 3 | | 2027 | 5 | | 2028 | 7 | **Formula:** `FACT('Node')` | Year | FACT Result | | ---- | ----------- | | 2025 | 1 | | 2026 | 6 | | 2027 | 120 | | 2028 | 5040 | --- # FALSE URL: https://docs.valsight.ai/false/ Description: The FALSE function returns 0 for every defined value in the input node. Undefined intersections remain undefined in the result. **Category:** [Logical functions](/logical-functions/) ## Overview The **FALSE** function **returns 0 for every defined value in the input node**. Undefined intersections remain undefined in the result. Use this function when you need a node of all zeros that matches the dimensionality of an existing node, for example as a baseline or reset value. ## Syntax `FALSE('Node')` **Example usage:** `FALSE('Revenue')` ## Parameters | Parameter | Description | Type | Required | | --------- | ---------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------------------- | | Dimensionality | Same as input. | | Values | **0** for every defined intersection. Undefined intersections remain undefined (N/A). | | Row count | Same as input. Only defined rows produce output. | ## Watch out * FALSE only covers **defined rows**. It does not create values where the input is undefined. If you need a 0 for each **undefined** row, look at the [IS\_NA](/is-na/) function, and invert its result with FALSE. * The input value itself does not matter. FALSE returns 0 regardless of whether the value is positive, negative, or zero. Only whether the value is defined matters. * Because 0 is interpreted as false in IF conditions, `FALSE('Node')` can be used as a condition that is always false for defined rows. * FALSE accepts expressions as input (e.g. `FALSE('A' + 'B')`). The result reflects the dimensionality and defined intersections of the combined expression. ## Examples ### Returns 0 for all defined rows This example shows FALSE returning 0 for every row that has a defined value in the input node. **Input node:** `'Revenue'` | Year | Value | | ---- | ----- | | 2025 | -24.5 | | 2026 | 95 | | 2027 | 110 | **Formula:** `FALSE('Revenue')` | Year | FALSE Result | | ---- | ------------ | | 2025 | 0 | | 2026 | 0 | | 2027 | 0 | ### FALSE applied to a combined expression When FALSE is applied to a sum of two nodes, it returns 0 for every row where the combined expression produces a defined value. **Input node:** `'Products'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | A | 67 | | 2026 | B | 85 | | 2027 | A | 954 | | 2027 | B | -54 | **Formula:** `FALSE('Revenue'+'Products')` | Year | FALSE Result | | ---- | ------------ | | 2025 | 0 | | 2026 | 0 | | 2027 | 0 | ### Undefined values are preserved FALSE only produces 0 for defined values. Rows where the input is undefined remain undefined in the result. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 95 | | 2026 | | | 2027 | 236 | **Formula:** `FALSE('A')` | Year | FALSE Result | | ---- | ------------ | | 2025 | 0 | | 2026 | | | 2027 | 0 | ## Related | Function | When to use instead | | ----------------- | -------------------------------------------------------------------------------------- | | [TRUE](/true/) | When you need 1 (true) for every defined value instead of 0. | | [IS\_NA](/is-na/) | When you need to detect undefined values (returns 1 where undefined, 0 where defined). | --- # Feature Deprecation URL: https://docs.valsight.ai/feature-deprecation/ Description: This page lists all features and functions that are deprecated and removed from Valsight. This page lists all features and functions that are deprecated and removed from Valsight. Removals of deprecated features will be announced via the Release Notes as soon as possible. Reasons for deprecations can be based on features no longer being up-to-date, not being a fit for Valsight any more, or reduced usage by customers. ## Deprecated and removed features | Feature | Deprecation first announced | Removal version | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | --------------- | | **Scenario Manager columns**
The Before/After and Impact columns in the Scenario Manager. | n/a | 6.0.0 | | **Feature flags**
`featureFlags.theme`
`featureFlags.bridgeCombinedEffects` (used to set a default, which has moved to the new chart editor)
`featureFlags.defaultFlexChartFilterYearIds`
`featureFlags.visibleNumbersDisplay`
`featureFlags.workspaceSnapshotCopyrightNoticeFontColor`
`featureFlags.workspaceSnapshotLogo` | n/a | 6.0.0 | | **Bridge settings**
The waterfall type settings and the primary display unit. | n/a | 6.0.0 | | **FX operation**
This node formula was previously used for currency conversion. The alternative approach is described in the internal modeling documentation and in the German Training Model T05. | Release Notes 5.0.0 | 5.0.1 | | **'Save' and 'Discard' function**
Used for saving and discarding changes in the workspace. Workspaces are now saved automatically. | Release Notes 5.3.0 | 5.4.0 | | **Old functionality to update dimensionality via Excel**
This functionality received a usability upgrade. The new functionality is described under [Updating level values via data source upload](/updating-level-values-via-data-source-upload/). | [Release Notes 5.8.0](/release-notes/) | 5.8.0 | --- # FILL_NA URL: https://docs.valsight.ai/fill-na/ Description: FILL_NA fills missing values (N/A) that result from pivoting a dimension into columns, replacing gaps with a specified value (default 0) on existing level combinations. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **FILL\_NA** function **fills missing values (N/A) on existing level combinations** after the specified dimension is pivoted into columns. Use this function when reshaping or pivoting creates missing cells and you want to explicitly fill those gaps with a specific value. ## Syntax `FILL_NA('Node' [, "Dimension" [, Value]])` ## Parameters | Parameter | Description | Type | Required | Default | | ------------- | ----------------------------------------------------------------------- | -------------- | -------- | ----------------------------------- | | **Node** | Node that may contain missing values (N/A). | Node reference | Yes | -- | | **Dimension** | Name of the dimension to pivot into columns before filling. | Dimension name | No | `"Time"` at the node's finest level | | **Value** | Value written into former missing cells on existing level combinations. | Number | No | `0` | ## Watch out * The node must already contain levels of the **specified dimension**. * The function fills only where the dimension is **pivoted into columns**. * It does **not** fill the complete time horizon and does not create missing level values that are not present in the input node (e.g., absent products). To fill missing values, use [FILLMISSING](/fillmissing/) or [FILLMISSING\_LAST](/fillmissing-last/). * Linked levels of the chosen dimension also appear as columns in the pivoted result. ## Examples ### Filling missing time values with 0 (default) This example fills missing values after pivoting the time dimension into columns. The default fill value is 0. The time horizon of the project is 2025-2028. The dimension `"ProductDimension"` consists of the level `"Product"` and the level values `"Car"`, `"Van"`, and `"Truck"`. The input node features the level values `"2026"`, `"2028"` and `"Car"`, `"Van"`. **Input node:** `'Input node'` | Year | Product | Value | | ---- | ------- | ----- | | 2026 | Car | 100 | | 2028 | Van | 90 | Pivoted `Input node` by dimension `"Time"` | Product | 2026 | 2028 | | ------- | ---- | ---- | | Car | 100 | N/A | | Van | N/A | 90 | **Formula:** `FILL_NA('Input node')` **Equivalent to:** `FILL_NA('Input node', "Time", 0)` | Product | 2026 | 2028 | | ------- | ---- | ---- | | Car | 100 | 0 | | Van | 0 | 90 | This function fills the missing level values of the finest time dimension with 0. Notice that the formula does not fill the complete time horizon (e.g. expands the years `"2025"` and `"2027"`). ### Filling along a custom dimension with a custom value This example fills missing values along the ProductDimension using 16 as the fill value instead of the default 0. **Formula:** `FILL_NA('Input node', "ProductDimension", 16)` | Year | Car | Van | | ---- | --- | --- | | 2026 | 100 | 16 | | 2028 | 16 | 90 | This function fills the missing level values of the dimension `"ProductDimension"` with `16`. Notice that the formula does not add any values available in the dimension that are not present in the input (e.g. `"Truck"`). ## Related | Function | When to use instead | | --------------------------------------- | ------------------------------------------------------------------------------------------------- | | [FILLMISSING](/fillmissing/) | When you want to add missing level values for a dimension, not just fill N/A cells from pivoting. | | [FILLMISSING\_LAST](/fillmissing-last/) | When you want to fill missing values using the last available value instead of a constant. | --- # FILLMISSING URL: https://docs.valsight.ai/fillmissing/ Description: The FILLMISSING function fills structurally missing level values of a specified dimension in a node with a constant value, using configurable behavior options to control which missing entries are filled. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **FILLMISSING** function **fills missing level values of a specified dimension into the input node's data.** The input node must already contain the levels of that dimension. FILLMISSING does not add new levels; it only fills missing level values of levels already present. Use this function when you want to fill structurally missing level values in an existing dimension with a constant value. ## Syntax `FILLMISSING('Node' [, "Dimension" [, Value [, "Behavior"]]])` **Example usage:** `FILLMISSING('Revenue')` ## Parameters | Parameter | Description | Type | Required | Default | | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | ----------------- | | **Node** | Input node with potentially missing level values, specified in single quotes (e.g.`'Revenue'`) | Node reference | Yes | -- | | **Dimension** | Name of the dimension whose level values will be used to fill the input node, specified in double quotes (e.g.`"ProductDimension"`) | Dimension name | No | Finest time level | | **Value** | Value written into newly filled rows | Number | No | `0` | | **Behavior** | Controls which missing entries are filled. Available values: `"All"`, `"StartAtFirst"`, `"FinishAtLast"`, `"Interval"` | Keyword | No | `"All"` | **Behavior options:** * `"All"`: Fills all missing values across the full project horizon. * `"StartAtFirst"`: Fills missing entries after the first present value per partition, through the end of the horizon. * `"FinishAtLast"`: Fills missing entries from the start of the horizon until the last present value per partition. * `"Interval"`: Fills missing entries only between the first and last present values per partition. ## Output shape | Aspect | Behavior | | -------------- | ---------------------------------------------------------------------------------------- | | Dimensionality | Unchanged (no levels added or removed) | | Values | Existing rows are preserved unchanged. New rows are added with the specified fill value. | | Row count | Increases to include filled missing level values | ## Watch out * The input node must already **contain levels** of the specified dimension. FILLMISSING does not add new levels to the node. * If the node has **linked levels**, you cannot fill values of the linked-to dimension. Fill the source dimension instead to get all valid values. * This function enforces level links from dimension management. **Do not use** this function if you want the node to have different level links than the dimensions. * The fill behavior operates **per partition**: for example, with `"StartAtFirst"`, the start point is determined separately for each product. ## Examples ### Fill missing values across the time horizon This example fills missing year and product values with a constant. The project time horizon is 2025-2028. The dimension `"ProductDimension"` consists of the level `"Product"` and the level values `"Car"`, `"Van"`, and `"Truck"`. The input node features the level values `"2025"`, `"2027"` and `"Car"`, `"Van"`. **Input node:** `'Input node'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | Car | 100 | | 2027 | Van | 90 | **Formula:** `FILLMISSING('Input node')` | Year | Product | FILLMISSING Result | | ---- | ------- | ------------------ | | 2025 | Car | 100 | | 2025 | Van | 0 | | 2026 | Car | 0 | | 2026 | Van | 0 | | 2027 | Car | 0 | | 2027 | Van | 90 | | 2028 | Car | 0 | | 2028 | Van | 0 | With no arguments, the input node is filled with the missing time level values (`2026`, `2028`) using the default value `0`. **Formula:** `FILLMISSING('Input node', "ProductDimension", 1)` | Year | Product | FILLMISSING Result | | ---- | ------- | ------------------ | | 2025 | Car | 100 | | 2025 | Van | 1 | | 2025 | Truck | 1 | | 2027 | Car | 1 | | 2027 | Van | 90 | | 2027 | Truck | 1 | Here, the input node is filled with the missing level values of `"ProductDimension"` (e.g. `"Truck"`). The fill value is `1`. ### Fill missing values with different behaviors This example uses the same input with different behavior settings to show how the fill range changes. **Input node:** `'Input node'` | Year | Product | Value | | ---- | ------- | ----- | | 2026 | Car | 100 | | 2027 | Van | 200 | | 2028 | Car | 300 | **Formula:** `FILLMISSING('Input node', "Time", 1, "All")` | Year | Product | FILLMISSING Result | | ---- | ------- | ------------------ | | 2025 | Car | 1 | | 2026 | Car | 100 | | 2027 | Car | 1 | | 2028 | Car | 300 | | 2025 | Van | 1 | | 2026 | Van | 1 | | 2027 | Van | 200 | | 2028 | Van | 1 | `"All"` fills empty values over the entire project horizon. **Formula:** `FILLMISSING('Input node', "Time", 1, "StartAtFirst")` | Year | Product | FILLMISSING Result | | ---- | ------- | ------------------ | | 2026 | Car | 100 | | 2027 | Car | 1 | | 2028 | Car | 300 | | 2027 | Van | 200 | | 2028 | Van | 1 | `"StartAtFirst"` fills after the first value present for each product through the end of the horizon. **Formula:** `FILLMISSING('Input node', "Time", 1, "FinishAtLast")` | Year | Product | FILLMISSING Result | | ---- | ------- | ------------------ | | 2025 | Car | 1 | | 2026 | Car | 100 | | 2027 | Car | 1 | | 2028 | Car | 300 | | 2025 | Van | 1 | | 2026 | Van | 1 | | 2027 | Van | 200 | `"FinishAtLast"` fills from the start of the horizon until the last value present for each product. **Formula:** `FILLMISSING('Input node', "Time", 1, "Interval")` | Year | Product | FILLMISSING Result | | ---- | ------- | ------------------ | | 2026 | Car | 100 | | 2027 | Car | 1 | | 2028 | Car | 300 | | 2027 | Van | 200 | `"Interval"` fills only between the first and last present values for each product. ### Fill missing values with linked levels Keep in mind that this function might change existing level values if the levels are linked. The result of this function always follows the links in the dimension table. **Input node:** `'Input'` | Month | CalendarMonth | Value | | ------- | ------------- | ----- | | 2025-02 | 06 | 100 | | 2025-03 | 06 | 105 | | 2025-04 | 11 | 110 | | 2025-05 | 05 | 115 | | 2025-06 | 06 | 120 | | 2025-07 | 02 | 125 | **Formula:** `FILLMISSING('Input', "TimeDimension", 15)` | Month | CalendarMonth | FILLMISSING Result | | ------- | ------------- | ------------------ | | 2025-01 | 01 | 15 | | 2025-02 | 02 | 100 | | 2025-03 | 03 | 105 | | 2025-04 | 04 | 110 | | 2025-05 | 05 | 115 | | 2025-06 | 06 | 120 | | 2025-07 | 07 | 125 | | 2025-08 | 08 | 15 | | 2025-09 | 09 | 15 | | 2025-10 | 10 | 15 | | 2025-11 | 11 | 15 | | 2025-12 | 12 | 15 | Notice that the CalendarMonth values in the input (06, 06, 11, 05, 06, 02) were corrected to match the dimension management links (01, 02, 03, ..., 12). FILLMISSING enforces the linked level values. ## Related | Function | When to use instead | | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | [FILLMISSING\_LAST](/fillmissing-last/) | When you want missing values filled using the last available value instead of a constant. | | [FILL\_NA](/fill-na/) | When you want to fill N/A values on existing level combinations after pivoting instead of adding missing level values for a dimension. | --- # FILLMISSING_LAST URL: https://docs.valsight.ai/fillmissing-last/ Description: The FILLMISSING_LAST function fills missing level values in a node by carrying forward the last observed value from a specified dimension, with a fallback constant value before the first data point. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **FILLMISSING\_LAST** function **fills missing level values using the last available value from a specified dimension in the input node.** If a row does not have a previous value, the Value parameter is used as fallback. The input node must already contain the levels of the dimension. If no dimension is specified, the default dimension is `"Time"`. Use this function when you want to fill structurally missing level values with the last available value instead of a constant. ## Syntax `FILLMISSING_LAST('Node' [, "Dimension" [, Value [, "Behavior"]]])` **Example usage:** `FILLMISSING_LAST('Revenue')` ## Parameters | Parameter | Description | Type | Required | Default | | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | ----------------- | | **Node** | Input node with potentially missing level values, specified in single quotes (e.g.`'Revenue'`) | Node reference | Yes | -- | | **Dimension** | Name of the dimension whose level values will be used to fill the input node, specified in double quotes (e.g.`"ProductDimension"`) | Dimension name | No | Finest time level | | **Value** | Fallback value used when there is no last available value (i.e. before the first data point) | Number | No | `0` | | **Behavior** | Controls which missing entries are filled. Available values: `"All"`, `"StartAtFirst"`, `"FinishAtLast"`, `"Interval"` | Keyword | No | `"All"` | **Behavior options:** * `"All"`: Fills all missing values. Before the first data point, the fallback Value is used. After the first data point, the last observed value is carried forward. * `"StartAtFirst"`: Starts filling from the first data point onward. No rows are generated before the first value. * `"FinishAtLast"`: Fills from the start of the horizon up to (and including) the last data point. No rows are generated after the last value. * `"Interval"`: Fills only between the first and last data points. No rows before first or after last. ## Output shape | Aspect | Behavior | | -------------- | ----------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Unchanged (no levels added or removed) | | Values | Existing rows preserved. New rows are filled with the last observed value, or the fallback Value before the first data point. | | Row count | Increases to include filled missing level values (extent depends on Behavior) | ## Watch out * The input node must already **contain levels** of the specified dimension. FILLMISSING\_LAST does not add new levels to the node. * The Value parameter is only used as a **fallback before the first observed data point**. After the first value, forward-fill (last observed value) applies regardless of the Value parameter. * If the node has **linked levels**, you cannot fill values of the linked-to dimension. Fill the source dimension instead to get all valid values. * This function enforces level links from dimension management. **Do not use** this function if you want the node to have different level links than the dimensions. * The fill operates **per partition**: with multiple non-target dimensions (e.g. products within years), the forward-fill runs independently for each partition. * If the input is empty, the function falls back to [FILLMISSING](/fillmissing/) behavior (constant fill). ## Examples ### Fill missing values across the time horizon This example fills missing year values using the last available value. The project time horizon is 2025-2029. The input node features the level values `"2026"` and `"2028"`. **Input node:** `'Input node'` | Year | Value | | ---- | ----- | | 2026 | 10 | | 2028 | 50 | **Formula:** `FILLMISSING_LAST('Input node')` | Year | FILLMISSING\_LAST Result | | ---- | ------------------------ | | 2025 | 0 | | 2026 | 10 | | 2027 | 10 | | 2028 | 50 | | 2029 | 50 | The value `10` from 2026 is carried forward to 2027. The value `50` from 2028 is carried forward to 2029. Before the first data point (2025), the default fallback value `0` is used. **Formula:** `FILLMISSING_LAST('Input node', "Time", 0, "StartAtFirst")` | Year | FILLMISSING\_LAST Result | | ---- | ------------------------ | | 2026 | 10 | | 2027 | 10 | | 2028 | 50 | | 2029 | 50 | `"StartAtFirst"` starts from the first available value (2026), so 2025 is omitted. **Formula:** `FILLMISSING_LAST('Input node', "Time", 0, "FinishAtLast")` | Year | FILLMISSING\_LAST Result | | ---- | ------------------------ | | 2025 | 0 | | 2026 | 10 | | 2027 | 10 | | 2028 | 50 | `"FinishAtLast"` fills until the last value (2028), so 2029 is omitted. **Formula:** `FILLMISSING_LAST('Input node', "Time", 0, "Interval")` | Year | FILLMISSING\_LAST Result | | ---- | ------------------------ | | 2026 | 10 | | 2027 | 10 | | 2028 | 50 | `"Interval"` fills only between the first (2026) and last (2028) present values. ### Fill missing values on a non-time dimension This example fills missing product values by carrying the last available product value forward within each year. The dimension `"ProductDimension"` consists of the level `"Product"` with values `"A"`, `"B"`, `"C"`, `"D"`, and `"E"`. **Input node:** `'Input node'` | Year | Product | Value | | ---- | ------- | ----- | | 2026 | B | 10 | | 2028 | C | 50 | | 2028 | E | 100 | **Formula:** `FILLMISSING_LAST('Input node', "ProductDimension")` | Year | Product | FILLMISSING\_LAST Result | | ---- | ------- | ------------------------ | | 2026 | A | 0 | | 2026 | B | 10 | | 2026 | C | 10 | | 2026 | D | 10 | | 2026 | E | 10 | | 2028 | A | 0 | | 2028 | B | 0 | | 2028 | C | 50 | | 2028 | D | 50 | | 2028 | E | 100 | For 2026, the first available product is `"B"` with value `10`, which is carried forward to `"C"`, `"D"`, `"E"`. Products before `"B"` get the fallback value `0`. For 2028, the forward-fill runs independently: `"C"` = **50** carries to `"D"`, then `"E"` = **100** takes over. **Formula:** `FILLMISSING_LAST('Input node', "ProductDimension", 0, "StartAtFirst")` | Year | Product | FILLMISSING\_LAST Result | | ---- | ------- | ------------------------ | | 2026 | B | 10 | | 2026 | C | 10 | | 2026 | D | 10 | | 2026 | E | 10 | | 2028 | C | 50 | | 2028 | D | 50 | | 2028 | E | 100 | `"StartAtFirst"` starts from the first available product in each year. **Formula:** `FILLMISSING_LAST('Input node', "ProductDimension", 0, "FinishAtLast")` | Year | Product | FILLMISSING\_LAST Result | | ---- | ------- | ------------------------ | | 2026 | A | 0 | | 2026 | B | 10 | | 2028 | A | 0 | | 2028 | B | 0 | | 2028 | C | 50 | | 2028 | D | 50 | | 2028 | E | 100 | `"FinishAtLast"` stops at the last available product in each year. **Formula:** `FILLMISSING_LAST('Input node', "ProductDimension", 0, "Interval")` | Year | Product | FILLMISSING\_LAST Result | | ---- | ------- | ------------------------ | | 2026 | B | 10 | | 2028 | C | 50 | | 2028 | D | 50 | | 2028 | E | 100 | `"Interval"` fills between first and last. For 2026, there is only one value (`"B"`), so no interval to fill. ## Related | Function | When to use instead | | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | [FILLMISSING](/fillmissing/) | When you want missing values filled with a constant instead of the last available value. | | [FILL\_NA](/fill-na/) | When you want to fill N/A values on existing level combinations after pivoting instead of adding missing level values for a dimension. | --- # FILTER URL: https://docs.valsight.ai/filter/ Description: The FILTER function returns only the rows of a node that match a specified condition. Rows that do not satisfy the filter condition are removed from the result. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **FILTER** function **returns only the rows** of a node **that match a specified condition**. Rows that do not satisfy the filter condition are removed from the result. Use this function to restrict calculations to a subset of your data, for example by selecting specific years, regions, or products. ## Syntax `FILTER('Node', "Level", FilterValue [, "FilterOperation"])` **Example usage:** `FILTER('Sales', "Year", "2025")` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------- | -------- | -------------- | | **Node** | Input node, specified in single quotes (e.g. `'Revenue'`) | Node reference | Yes | -- | | **Level** | The level by which the input node shall be filtered, specified in double quotes (e.g. `"Year"`, `"Region"`) | Level name | Yes | -- | | **FilterValue** | The value(s) to filter by. A single level value or a list of level values (e.g. `"2026"` or `["EMEA", "APAC"]`) | Level value / Level value list | Yes | -- | | **FilterOperation** | Defines how values are compared to the filter. Valid values: `"EQ"`, `"NEQ"`, `"LT"`, `"LTE"`, `"GT"`, `"GTE"` | String | No | `"EQ"` (equal) | **See also:** [Comparisons & boolean operators](/comparisons-boolean-operators/) ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------ | | Dimensionality | Same dimensions as the input node | | Values | Only rows fulfilling the filter condition are returned | | Row count | Reduced, non-matching rows are removed | ## Watch out * FILTER **removes rows** that do not match the filter condition. * When using a **list of values**, rows matching any value in the list are kept. * Filters can be **nested** to restrict multiple dimensions. * The level specified in the filter must exist in the input node. ## Examples **Input node:** `'Sales'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | Alpha | 100 | | 2025 | Beta | 200 | | 2026 | Alpha | 150 | | 2026 | Beta | 300 | | 2027 | Alpha | 10 | ### Filter to a single value Keep only rows for 2025. **Formula:** `FILTER('Sales', "Year", "2025")` | Year | Product | FILTER Result | | ---- | ------- | ------------- | | 2025 | Alpha | 100 | | 2025 | Beta | 200 | ### Exclude specific values with NEQ (not equal) Return all rows **except** 2025 and 2026. **Formula:** `FILTER('Sales', "Year", ["2025", "2026"], "NEQ")` | Year | Product | FILTER Result | | ---- | ------- | ------------- | | 2027 | Alpha | 10 | ### Chaining filters You can nest FILTER calls to narrow down on multiple dimensions at once. **Formula:** `FILTER(FILTER('Sales', "Year", "2026"), "Product", "Alpha")` | Year | Product | FILTER Result | | ---- | ------- | ------------- | | 2026 | Alpha | 150 | ### Using a project variable as the filter value Instead of hardcoding a level value for a specific year, you can use a project variable so the filter updates automatically when the variable changes. **Formula:** `FILTER('Sales', "Year", "$FC_End")` This returns only rows where Year equals the current value of `$FC_End`, no formula change needed when the planning horizon shifts. **See also:** [Project Variables](/project-variables/) ## Related | Function | When to use instead | | ------------------------------ | ------------------------------------------------------------------------------------------ | | [IF](/if/) | Apply conditional logic without removing rows. | | [LEVELFILTER](/levelfilter/) | When the condition depends on comparing level values rather than matching explicit values. | | [EXPANDSINGLE](/expandsingle/) | Expand to specific level values instead of removing rows. | | [DATA](/data/) | Load source data before filtering. | --- # Filtering & data shaping URL: https://docs.valsight.ai/filtering-data-shaping/ Description: Use this category when you need to restrict results to a subset, select representative values per group, fill missing combinations, or create helper tables such as ranks and enumerations. Use this category when you need to **restrict results to a subset, select representative values per group, fill missing combinations, or create helper tables** such as ranks and enumerations. These functions help you shape the result set without changing overall dimensionality. ## Start here if you want to: * **Filter** a node to specific level values, for example EMEA or APAC only * **Pick** one value per group * **Fill missing** level values or combinations so calculations don’t break * Use **ranking / enumeration** helpers for further logic ## Not here if you want to: * Reshape dimensionality → see [Dimensionality & hierarchies](/dimensionality-hierarchies/) * Use time comparisons or time-based logic → see [Compare periods](/compare-periods/) or [Rollforward & time series](/rollforward-time-series/) ## Mental model * **Filter** functions keep only rows that match a level value or condition * **Pick** functions select one value per group * **Fill** functions add missing level values or combinations * **Rank** functions generate helper indices based on value order or dimension order * **Map** functions translate values through a lookup or threshold table ## Common patterns | Name | What it does | Formula | | ----------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------- | | Filter to a list of level values | Use when you want a subset based on explicit level values. | `FILTER('Node', "Level", ["A", "B"])` | | Filter by comparing level values | Use when the filter depends on comparing one level value to another. | `LEVELFILTER('Node', "Level1", "Level2")` | | Pick the first value per group | Use when you need a single representative value per group. | `FINDFIRST('Node')` | | Fill missing level values | Use when you want all level values of a dimension to be present. | `FILLMISSING('Node')` | | Carry the last value forward | Use when you want to fill gaps with the last known value. | `FILLMISSING_LAST('Node')` | | Fill missing values after reshaping | Use when reshaping or pivoting created missing cells to fill. | `FILL_NA('Node')` | | Flag missing combinations | Use when you want to spot mismatched combinations between two nodes. | `FINDMISSING('Node1', 'Node2')` | | Create a rank or enumeration helper | Use when you need indices for sorting, thresholds, or rule logic. | `ENUM('Node')` or `ENUM_LEVEL("Level")` | | Map values through a lookup table | Use when you need threshold-based mapping from one measure to another. | `LOOKUP('LookupValue', 'Index', 'ReturnValue')` | ## Functions in this category | Function | Description | | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | [FILTER](/filter/) | Filters the node to rows where the specified level satisfies the filter operation. | | [LEVELFILTER](/levelfilter/) | Filters the node to rows where a comparison between two level values meets a specified condition. | | [FINDFIRST](/findfirst/) | Returns the first value per group defined by the specified level. | | [FILLMISSING](/fillmissing/) | Fills missing level values for a dimension into the node’s data. | | [FILLMISSING\_LAST](/fillmissing-last/) | Fills missing level values for a dimension with the last available value in the node. | | [FILL\_NA](/fill-na/) | Fills missing (NA) values for existing level combinations after pivoting a dimension into columns. | | [FINDMISSING](/findmissing/) | Marks missing level values between two nodes as 1 and existing ones as 0. | | [ENUM](/enum/) | Numbers rows in ascending or descending order by value magnitude. | | [ENUM\_LEVEL](/enum-level/) | Numbers level values ascending or descending in the order defined in dimension management. | | [LOOKUP](/lookup/) | Looks up a value in an index table and returns the corresponding value from a return table using threshold (approximate) matching. | ## Choosing between similar functions **FILTER vs LEVELFILTER** * Use `FILTER` when you filter by explicit level values or simple conditions on one level * Use `LEVELFILTER` when the filter depends on comparing level values **FILLMISSING vs FILLMISSING\_LAST** * Use `FILLMISSING` when you want to add missing values using a defined fill behavior * Use `FILLMISSING_LAST` when you want to fill gaps with the last available value **FILLMISSING vs FILL\_NA** * Use `FILLMISSING` when you want to add missing values for a dimension or level * Use `FILL_NA` when reshaping created missing cells and you want to fill only those cells **FINDFIRST vs ENUM / ENUM\_LEVEL** * Use `FINDFIRST` when you want to select one value per group * Use `ENUM` / `ENUM_LEVEL` when you want an index or ordering helper **FINDMISSING vs IS\_NA** * Use `FINDMISSING` when you want to compare two nodes and detect missing combinations between them * Use `IS_NA` when you want to detect undefined values in a single node ## Pitfalls & troubleshooting * **FILTER returns empty:** confirm level values match exactly (spelling/case) and the referenced level is correct * **More rows than expected after filling:** confirm that you are filling the intended dimension or level * **Unexpected missing values after reshaping:** use `FILL_NA` or a diagnostic helper node to inspect missing intersections * **Single-node missingness checks**: use `IS_NA` when you need a diagnostic flag for undefined values ## Related * [Dimensionality & hierarchies](/dimensionality-hierarchies/): reshape functions often used before or after filtering * [Logical functions](/logical-functions/): comparisons and condition logic used together with filtering * [Troubleshooting guide](/troubleshooting-guide/): empty results and missing value behavior * [Function catalog](/function-catalog/): full signatures, parameters, and examples --- # Filters in Valsight URL: https://docs.valsight.ai/filters-in-valsight/ Description: - Setting filters can be done at multiple places within Valsight Setting filters can be done at multiple places within Valsight — workspaces, sheets, perspectives, charts, and the line-items in the Scenario Manager. The filter management dialog employs the same behavior and functions in all places it is used at, and two available select modes help you work flexibly while setting or removing filters. The first four are view filters: they change what you see without changing any values. A line-item filter is different in kind. It defines which slice of the model the line-item's values apply to, so it changes the simulation itself. --- # Finance functions URL: https://docs.valsight.ai/finance-functions/ Description: Use this category when you need standard financial calculations such as present value, future value, annuity payments, discounting, and investment appraisal. Use this category when you need **standard financial calculations** such as present value, future value, annuity payments, discounting, and investment appraisal. These functions are typically used for cash flow modeling, financing schedules, valuation, and depreciation. ## Start here if you want to: * **Discount cash flows**, for example with `NPV` or `PV` * Use an **investment return metric**, for example `IRR` * Use **annuity-style calculations** such as payments, periods, or rate * Use **depreciation logic** per period ## Not here if you want to: * Use rollforward logic, running totals, or projections → see [Rollforward & time series](/rollforward-time-series/) * Use numeric helpers such as rounding, min/max, logs → see [Math & numeric](/math-numeric/) ## Mental model * Most finance functions assume a **rate per period** and a **time series of payments or cash flows** * Results are sensitive to: * the time granularity, for example month vs year * the sign convention, for example inflows vs outflows * whether inputs are complete, since missing values can break calculations ## Common patterns | Name | What it does | Formula | | ------------------------------- | ------------------------------------------------------------------------------- | -------------------------------------------------- | | Discount a series of cash flows | Use when you want net present value at a discount rate. | `NPV('DiscountRate', 'CashFlow')` | | Compute internal rate of return | Use when you want the discount rate that sets `NPV` to zero. | `IRR('CashFlow')` | | Calculate a periodic payment | Use for annuity payments like loan repayment, leasing, or savings plans. | `PMT('Rate', 'Periods', 'PresentValue')` | | Solve for number of periods | Use when rate and payment are known and you want the duration. | `NPER('Rate', 'Payment', 'PresentValue')` | | Solve for the rate | Use when periods and payments are known and you need the implied interest rate. | `RATE('Periods', 'Payment', 'PresentValue', …)` | | Compute present value | Use when you want to discount an annuity-like stream into a present value. | `PV('Rate', 'Periods', 'Payment', …)` | | Compute future value | Use when you want to project an annuity-like stream into the future. | `FV('Rate', 'Periods', 'Payment', …)` | | Model depreciation per period | Use when you want straight-line depreciation over time. | `DEPRECIATION('InitialValue', 'DepreciationTime')` | ## Functions in this category | Function | Description | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | | [NPV](/npv/) | Calculates net present value from a discount rate and a series of cash flows. | | [IRR](/irr/) | Calculates the internal rate of return. | | [PV](/pv/) | Calculates present value given rate, periods, payments, and future value/type. | | [FV](/fv/) | Calculates the future value of a recurring annuity given interest rate, periods, and payments. | | [PMT](/pmt/) | Calculates the periodic payment for an investment given rate, periods, and present value. | | [NPER](/nper/) | Calculates the number of periods for an investment given rate, payment, and present value. | | [RATE](/rate/) | Solves for the interest rate per period of an annuity given periods, payments, present value, and optional parameters. | | [DEPRECIATION](/depreciation/) | Calculates straight-line depreciation per period from initial value and depreciation time. | ## Choosing between similar functions **NPV vs PV** * Use `NPV` to discount a cash flow series into a single net present value * Use `PV` for present value of an annuity-style stream with structured parameters **IRR vs NPV** * Use `NPV` when the discount rate is known and you want the value * Use `IRR` when the value target is `NPV = 0` and you want the implied rate **PMT vs PV/FV** * Use `PMT` when you want the periodic payment * Use `PV` or `FV` when you want present or future value given payment and rate **NPER vs RATE** * Use `NPER` when the rate is known and you want the number of periods * Use `RATE` when the number of periods is known and you want the implied rate ## Pitfalls & troubleshooting * **Rate scaling errors:** if results are off by a large factor, confirm your rate is per period, for example monthly vs yearly * **IRR instability:** `IRR` needs cash flows with at least one sign change (mix of inflows and outflows) * **Missing values:** if results are missing, check whether inputs are missing at the same intersections * **Too much dimensionality:** if cash flow nodes have extra dimensions such as Product or Region, validate one representative slice first before rolling up * **Depreciation timing mismatch:** if depreciation looks shifted, confirm that depreciation time aligns with your project’s time granularity ## Related * [Math & numeric](/math-numeric/): rounding and helpers often used around finance results * [Rollforward & time series](/rollforward-time-series/): project cash flows and build time-based schedules * [Troubleshooting guide](/troubleshooting-guide/): missing values and unexpected results * [Function catalog](/function-catalog/): full signatures, parameters, and examples --- # FINDFIRST URL: https://docs.valsight.ai/findfirst/ Description: Returns the first defined value per group along a given level. If no level is given, the function automatically uses the lowest level in the time dimension used by the node. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **FINDFIRST** function **returns the first defined value per group along a given level**. If no level is given, the function automatically uses the lowest level in the time dimension used by the node. Use this function when you need to select one representative value per group, for example the first entry per product or the starting value in a time series. It is often paired with [TRUE](/true/) to generate starting values, for example with [SCHEDULEPROJECTS](/scheduleprojects/): `TRUE(FINDFIRST('Node'))`. ## Syntax `FINDFIRST('Node'[, "Level"])` ## Parameters | Parameter | Description | Type | Required | | --------- | ------------------------------------------------------------------------------------------------------------ | -------------- | -------- | | **Node** | Input node. | Node reference | Yes | | **Level** | The name of the level to find the first values in respect to. Defaults to the lowest time level on the node. | Level name | No | ## Watch out An error will occur: * If no level is provided and the node does not use the **time dimension**. * The **level must be present** on the entered node. * The level to find can **not be higher** in the dimension than the level used in the node (e.g. if the node uses `"Month"` the level can not be `"Year"`). * Hint: use [ROLLUP](/rollup/) or [DROPLEVEL](/droplevel/) in this case. ## Examples ### First value per product along the time dimension This example returns only the earliest defined value for each product. Products with gaps retain only the first year's value. **Input node:** `'Node A'` | | 2025 | 2026 | 2027 | 2028 | | --------- | ---- | ---- | ---- | ---- | | Product A | 4.5 | 4.5 | | 4.5 | | Product B | | 5 | 6 | 6.4 | | Product C | | | | 7 | | Product D | | | 5.6 | 5.6 | **Formula:** `FINDFIRST('Node A')` **Equivalent to:** `FINDFIRST('Node A', "Year")` | | 2025 | 2026 | 2027 | 2028 | | --------- | ---- | ---- | ---- | ---- | | Product A | 4.5 | | | | | Product B | | 5 | | | | Product C | | | | 7 | | Product D | | | 5.6 | | ## Related | Function | When to use instead | | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | [ENUM](/enum/) | When you want an index or ordering helper based on measure values rather than selecting one value per group. | | [ENUM\_LEVEL](/enum-level/) | When you want an index based on the order of level values in dimension management rather than selecting one value per group. | --- # FINDMISSING URL: https://docs.valsight.ai/findmissing/ Description: FINDMISSING compares two nodes and identifies missing level combinations by marking them as 1 (missing) or 0 (existing), with configurable behavior to check the first node, second node, or both for missing values. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **FINDMISSING** function **compares two nodes and marks missing level combinations as 1 and existing ones as 0**. Dependent on the Behavior input, the function finds missing level values in either or both of the nodes. Use this function when you need to compare two nodes and identify which level combinations are missing in one or both. ## Syntax `FINDMISSING('Node 1', 'Node 2' [, Behavior])` ## Parameters | Parameter | Description | Type | Required | Default | | ------------ | --------------------------------------------------------------- | -------------- | -------- | --------- | | **Node 1** | First input node. | Node reference | Yes | -- | | **Node 2** | Second input node. | Node reference | Yes | -- | | **Behavior** | Indicates the leading node which is checked for missing values. | Keyword | No | `"FIRST"` | **Behavior options:** * `"FIRST"`: The first node is checked for missing values. This is the default. * `"SECOND"`: The second node is checked for missing values. * `"BOTH"`: Checks the combined data of Node 1 and Node 2 for missing values. ## Watch out * When Behavior is `"BOTH"`, all inputs must have the **same dimensionality**. ## Examples **Input node:** `'Node A'` | Year | Product | Volume | | ---- | ------- | ------ | | 2025 | Alpha | 10 | | 2025 | Blade | 5 | | 2025 | Droplet | 7 | | 2026 | Alpha | 12 | | 2026 | Blade | 6 | | 2026 | Droplet | 9 | **Input node:** `'Node B'` | Product | Price | | ------- | ----- | | Alpha | 55 | | Blade | 65 | | Gamma | 80 | **Input node:** `'Node C'` | Year | Product | Volume | | ---- | ------- | ------ | | 2025 | Alpha | 10 | | 2025 | Gamma | 5 | ### Checking the first node for missing level values (default) This example keeps Node A's rows and flags the product level values that are missing from Node B. Droplet is in Node A but not in Node B, so it is flagged with 1. **Formula:** `FINDMISSING('Node A', 'Node B')` **Equivalent to:** `FINDMISSING('Node A', 'Node B', "FIRST")` | Year | Product | FINDMISSING Result | | ---- | ------- | ------------------ | | 2025 | Alpha | 0 | | 2025 | Blade | 0 | | 2025 | Droplet | 1 | | 2026 | Alpha | 0 | | 2026 | Blade | 0 | | 2026 | Droplet | 1 | ### Checking the second node for missing level values This example keeps Node B's rows and flags the product level values that are missing from Node A. Gamma is in Node B but not in Node A, so it is flagged with 1. **Formula:** `FINDMISSING('Node A', 'Node B', "SECOND")` | Product | FINDMISSING Result | | ------- | ------------------ | | Alpha | 0 | | Blade | 0 | | Gamma | 1 | ### Checking both nodes for missing combinations With BOTH, the function returns every level combination that is present in either node and flags those missing from the other. It is the union of the two inputs' rows, not a cross product, so a combination that exists in neither node (2026 and Gamma below) does not appear at all. **Formula:** `FINDMISSING('Node A', 'Node C', "BOTH")` | Year | Product | FINDMISSING Result | | ---- | ------- | ------------------ | | 2025 | Alpha | 0 | | 2025 | Blade | 1 | | 2025 | Droplet | 1 | | 2025 | Gamma | 1 | | 2026 | Alpha | 1 | | 2026 | Blade | 1 | | 2026 | Droplet | 1 | ## Related | Function | When to use instead | | ----------------- | ------------------------------------------------------------------------------------------ | | [IS\_NA](/is-na/) | When you need to detect undefined values in a single node rather than comparing two nodes. | --- # Formula basics URL: https://docs.valsight.ai/formula-basics/ Description: Formulas define how a node is calculated in a model. They combine node references, operators, and functions to calculate values across time and other business dimensions. Formulas define how a node is calculated in a model. They combine **node references, operators, and functions** to calculate values across time and other business dimensions. Learn the core syntax here before diving into the full [Operators](/operators/) reference and the [Function catalog](/function-catalog/). ## The building blocks | Term | Definition | | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Node references | Wrap node names in single quotes: `'Revenue'`. Typing a `'` in the Function Editor lists the available nodes, including nodes from submodels. | | Constants | Write numbers directly in formulas: `0`, `1.2`, `100000`. Numbers have no dimensions; they are a single value. | | Operators | Arithmetic `+`, `-`, `*`, `/`, `%`; comparisons `=`, `!=`, `<`, `<=`, `>`, `>=`; and the boolean operators `&&` and `\|\|`. [Operators](/operators/) can be nested and combined with functions. `AND`, `OR`, `XOR`, `NOT`, `TRUE` and `FALSE` are written as functions with parentheses, not as operators. | | Functions | [Functions](/function-catalog/) are named operations that transform, filter, or compare values. Names are case-sensitive and written in uppercase, for example `EXPAND`, `FILTER`, `IF`, take comma-separated arguments inside parentheses, and are evaluated inside out. | | Dimensions, levels,
and level values | [Dimensions and levels](/dimensions/) describe which business axes a value is defined on and at what detail. Use double quotes for dimension names, level names, and level values: `"Time"`, `"Year"`, `"2026"`. | | Value lists | Use square brackets for lists of values: `["EMEA", "APAC"]`. | | Project variables | Use [project variables](/project-variables/) as placeholders in functions. Type `$` to select a variable from the list, for example `$FORECAST_START`. | | Comments | Use `#` to add comments in the function field. | ## Editor assistance The Function Editor actively helps you write correct formulas. **Context-aware autocomplete.** As you type, the editor suggests the values that make sense in that position, following the dimension → level → level value hierarchy. Beyond node references, it now completes dimensions, levels, level values, data sources, tables and measures, models, and project variables — each labeled with where it comes from, for example "Level in *dimension*" or "Measure in *table*". **Inline signature help.** While your cursor is inside a function's parentheses, the editor shows that function's parameters, so you can see what each argument expects as you type. **Human-readable error messages.** When a formula has a problem, the editor explains it in plain language instead of a generic syntax error, for example: * Unknown functions, with a "did you mean …?" suggestion for a close match. * Unbalanced brackets or parentheses — a missing or extra `]` or `)`. * Unclosed quotes — a missing closing `"` or `'`. * Missing separators, such as a comma between arguments. * Unknown dimensions, levels, nodes, data sources, or project variables, with hints when a name needs single instead of double quotes. ## Common formula shapes | Name | What it does | Formula | | ----------------- | -------------------------------------------------------------------- | --------------------------------------------- | | Arithmetic | Combine node values directly with operators. | `'Revenue' - 'COGS'` | | Data reference | Pull uploaded or source data into a node. | `DATA("ERP", "Actuals", "Volume")` | | Reshaping | Add dimensional detail with one or more levels. | `EXPAND('Sales', "Product")` | | Filtering | Keep only the rows that match a set of level values. | `FILTER('Sales', "Region", ["EMEA", "APAC"])` | | Conditional logic | Return one value where a condition holds, another where it does not. | `IF('Margin' < 0, 0, 'Margin')` | ## Related * [Operators](/operators/): arithmetic, comparisons, and boolean logic used in formulas * [Function catalog](/function-catalog/): all functions (A-Z and browse by category) * [Troubleshooting guide](/troubleshooting-guide/): wrong shape, missing values, and common pitfalls --- # Frequently Asked Questions (FAQ) URL: https://docs.valsight.ai/frequently-asked-questions-faq/ Description: In unseren FAQs beantworten wir häufig gestellte Fragen zur Software. Auf der Seite befinden sich hilfreiche Informationen zu allgemeinen und spezifischen Th… In unseren FAQs beantworten wir häufig gestellte Fragen zur Software. Auf der Seite befinden sich hilfreiche Informationen zu allgemeinen und spezifischen Themen rund um die Anwendung. ## Daten **Meine Daten sind nicht in einer Standard-Upload-Tabelle strukturiert. Was kann ich tun?** Die einfachste Lösung ist, die [Neustrukturierung der Daten mit Hilfe von Excel Power Query](/restructuring-data-in-excel-using-power-query/). Alternativ dazu können Sie den [mehrdimensionalen Daten-Upload (2D/3D/4D-Tabellen)](/multidimensional-data-upload-2d-3d-4d-tables/) verwenden. **Ich sehe nicht die Daten, die ich erwarte. Was kann ich tun?** Überprüfen Sie zunächst, ob Ihre Daten korrekt hochgeladen wurden, indem Sie den Inhalt der Tabelle in der Datenquellenübersicht überprüfen. Danach können Sie den [Daten-Upload-Assistenten](/create-and-update-data-sources-step-by-step/) verwenden, um das Problem zu finden. Sie können auch manuell [validieren](/validate-dimensions/), um herauszufinden, was passiert ist. ## Benutzer **Kann ich neue Benutzer oder Gruppen zu Valsight hinzufügen?** Sie können Benutzer und Gruppen hinzufügen, wie unter [Projektrechte](/project-rights/) angegeben. **Wie verwalte ich, wer Zugang zu einem Projekt, Modell oder Arbeitsbereich hat?** Mit den [Projektrechten](/project-rights/) können Sie für jedes Projekt, Modell und jeden Arbeitsbereich unterschiedliche Berechtigungen festlegen. **Ist es möglich, dass sich zwei Personen gleichzeitig in einem Modell befinden, sodass eine Person im Modell arbeitet und die andere zuschauen kann?** Ja. Paralleles Arbeiten wird direkt unterstützt: Mehrere Personen können dasselbe Modell gleichzeitig öffnen und darin arbeiten. Objekte, die gerade bearbeitet werden, sind für die anderen gesperrt und bleiben im Lesemodus sichtbar, und Änderungen werden in Echtzeit synchronisiert. Die frühere Tastenkombination "SHIFT + A" wird nicht mehr benötigt. Siehe [Parallel Access in the Model Editor](/parallel-access-in-the-model-editor/). ## Modellieren **Wie kann ich Prozentwerte in Wachstumswerte umwandeln (1% → 1,01 und umgekehrt)?** Dazu können Sie die Funktion [ADDEACH](/addeach/) verwenden. **Wie kann ich mehrere Währungen in mein Modell implementieren?** Legen Sie eine eigene Dimension für die Währungen an (siehe [Funktionsweise von Dimensionen](/how-dimensions-work/)) und laden Sie die Wechselkurse per [DATA](/data/)-Funktion in Ihr Modell. **Wie lässt sich ein Teil eines Modells oder das gesamte Modell in ein anderes kopieren?** Dazu gibt es zwei Optionen: Option 1: Bei dieser Option können die Knoten als "Code" kopiert und an anderer Stelle wieder eingefügt werden. Gegebenenfalls treten hierbei Problem bei Zugriff in Submodelle auf. In diesem Fall könnte man die betroffenen Formeln zunächst erstmal leer kopieren. Option 2: In der "Knotenliste" (Projekteinstellungen → Show models → Nodes / see list) können ein oder mehrere Knoten markiert und in ein Modell kopiert. Jedoch wird dabei der komplette Teilbaum bis runter auf die Datenbasis kopiert. Nach dem kopieren liegen die Knoten alle "übereinander" sodass diese noch in die richtige Ecke bewegt werden müssen. Eine ausführliche Beschreibung finden Sie [hier](/duplicating-a-project/). **Wie lässt sich die Maximum Cube Size erhöhen?** Die "featureFlags.maxDataFrameSize" ist eine globale Einstellung und kann von einem Benutzer mit Admin-Rechten in den Systemeinstellungen (Configuration → Settings → Calculation) angepasst werden. Der Standardwert ist 12 (Angabe in MB). Die Einstellung gilt für die gesamte Instanz und nicht für ein einzelnes Projekt. Hinweis: Eine deutliche Erhöhung kann zu einer Performancebeeinträchtigung führen. Weitere Informationen finden Sie [hier](/limitations-data-sizing-guidelines/). **Wie lässt sich der Simulationshorizont eines Modells anpassen?** Um den [Simulationshorizont anzupassen](/changing-the-time-horizon/) muss zunächst das Modell ausgewählt werden. Im Anschluss kann man auf der rechten Seite den Horizont sowohl auf Jahr als auch auf Monat einstellen. Dabei können unter anderem auch andere Jahre eingetragen werden. **Gibt es eine Möglichkeit den Knotentyp bei Bedarf individuell anzupassen?** In der Regel reichen die 4 vorgegebenen Knotentypen für Modellierungen aus. Diese können auf der rechten Seite im Knoten-Editor ausgewählt werden. Neben Farbe, Namen etc. können auch die Simulierbarkeit, die Aggregations-Einstellungen und Validierungseinstellungen und [erweiterte Einstellungen](/advanced-node-settings/) eingeblendet und individuell angepasst werden. **Wie kann der Blattschutz von heruntergeladenen Excel Dateien aus dem Szenario Manager aufgehoben werden? Gibt es ein generisches Passwort?** In den Systemeinstellungen (Configuration → Settings → Security) kann ein Benutzer mit Admin Rechten das Passwort festlegen (parameterWorkbookProtectionPassword). Ein generisches Passwort gibt es dabei nicht. Desweiteren können Einstellungen bezüglich der Loginversuche, und der Anzahl der Minuten die ein Nutzer bei mehrfacher fehlerhafter Passworteingabe blockiert ist vorgenommen werden. **Wie ist es möglich ein bestehendes Modell in ein anderes Projekt zu kopieren?** Das Kopieren eines Modells in ein anderes Projekt ist in einigen Arbeitsschritten möglich. Dieser Vorgang wird [hier](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5641961808_Valsight_Modell-in-ein-anderes-Projekt-kopieren.pdf) ausführlich beschrieben. **Was ist bei der Entkopplung und Verschiebung von einem gekoppelten Level zu beachten?** Es muss darauf geachtet werden, dass die Annahmen nicht auf einem Knoten definiert sind, die das zu entkoppelnde Level benutzen, z.B. in EXPAND oder DROPLEVEL Funktionen. Um dies herauszufinden ist eine Suche mit dem Definition Editor hilfreich (Link: [Working with the Model Definition Editor](/working-with-the-model-definition-editor/)). **Falls Sie keine passende Antwort auf Ihre Frage finden konnten, wenden Sie sich gerne an unseren Support!** **** --- # FAQ: AI Assistant URL: https://docs.valsight.ai/frequently-asked-questions-valsight-ai-assistant/ Description: When will the Valsight AI Assistant be rolled out for me? Common questions about the Valsight AI Assistant: when it becomes available, how your data is handled, what it can answer, and what it costs. **Editing is coming soon.** The Assistant is read-only today; the ability to have it build and change models for you is in development and will arrive in a future release. If you want an AI client to work with your models now, see the [Valsight MCP integration](/valsight-mcp-server/). **When will the Valsight AI Assistant be rolled out for me?** From the 7.0 release onward, the Valsight AI Assistant can be enabled. A key prerequisite is your active consent to the required contract amendments and/or data protection terms. Usage is token-based, optional, and can be enabled per instance on request; we will inform you separately before activation. **Are my data secure?** Yes. The AI has no access to numeric values; it bases its answers exclusively on the Valsight documentation and on project structures information like models, dimensions and formulas to generate explanations and suggestions. Customer data is kept separate and confidential and our LLMs do not train on or store any customer information. Existing access rights remain unchanged: the AI operates in read-only mode and can access projects only with the respective user permissions - it cannot see more than the signed-in person. An external review of the Valsight Assistant by an independent auditor (penetration test) has already been completed with no security vulnerabilities identified. **Can AI change my projects?** No. The Assistant runs in read-only mode - no write permissions and no changes to models, data, or scenarios. It can explain and make suggestions; implementation remains with you. **Can I trust the answers?** As decision support - not as a single source of truth. The Assistant derives its answers from your model structure and the available data, and helps make relationships visible. The business review remains with you - please validate suggestions and explanations before adopting them. **What can the Valsight AI Assistant help me with?** The assistant can help you: * Understand model structure and node relationships * Explain formulas and calculations * Navigate data sources and identify relevant tables * Learn Valsight features and operations * Get quick answers to modeling questions It works best for explanatory and guidance questions about your specific model. **What data does the AI have access to?** The AI can see: * Model structure (nodes, connections, hierarchies) * Formulas and operation syntax * Data source names, tables, and column metadata * Project configuration and annotations The AI cannot see: * Numeric values in your data * Actual calculation results * User credentials or personal information * Projects you don't have permission to access **Can I use Valsight AI Assistant with any model?** Yes. The assistant works with any Valsight model you have access to. It automatically adapts to your model's structure and data sources. The more annotations and descriptions you've added to your model, the more contextual the AI's answers will be. **Does my chat history persist?** Yes, but only per browser tab and for the session. Each tab maintains its own independent conversation. Your chat history remains available even if you refresh the page, but closing the tab will clear the entire conversation. There is no longterm chat history. **What if the chat gets stuck or doesn't respond?** If the AI doesn't respond within 30 seconds: 1. Check your internet connection 2. Refresh the page and try again 3. Rephrase your question to be more specific 4. Try a simpler question first to test connectivity The chat interface is designed to remain responsive. If you experience persistent issues, contact your Valsight administrator. **Can I ask questions in any language?** The AI Assistant is optimized for English. While it may understand questions in other languages, response quality and accuracy are best when using English. **What happens if the AI makes an error in its response?** The AI generates responses based on your model structure and available documentation. If an answer seems incorrect: 1. Rate the response with thumbs down to provide feedback 2. Verify the information against your model directly 3. Rephrase your question with more specific details 4. Remember: the AI Assistant is a support tool - always validate important information The AI learns from your feedback to improve over time. **Are there limits to how much I can use the AI?** Usage is token-based and subject to limits. If you encounter usage restrictions: * Contact your Valsight administrator for information about your instance's limits * Detailed rate limit information will be provided during rollout **How do I rate AI responses?** After each AI response, you'll see thumbs up and thumbs down buttons. Click the button that reflects your experience: * **Thumbs up**: The answer was helpful, accurate, and relevant * **Thumbs down**: The answer was unhelpful, incorrect, or off-topic Ratings are optional but help improve the AI Assistant. Once submitted, ratings cannot be changed. **Can the AI perform calculations for me?** No. The AI cannot access numeric values or perform calculations. It can explain how formulas work and what calculations your model performs, but it cannot compute actual results. **Does the AI understand my business context?** The AI understands your model's technical structure but not your specific business meaning unless you've documented it. To get better answers: * Add descriptions to your nodes * Include annotations explaining business logic * Use clear, descriptive names for nodes and data sources The more context you provide in your model, the more relevant the AI's answers will be. **Can other users see my conversations?** No. Your AI conversations are private and not shared with other users. Each user has their own independent conversations based on their access permissions. However, your conversations will be logged for audit reasons. **What if I have a question the AI can't answer?** The AI is designed to help with model structure, formulas, and Valsight features. For questions outside this scope: * Check the full Valsight documentation * Contact Valsight support for technical issues * Reach out to your internal Valsight administrators * Consult with your team for business-specific guidance ## Related * [Valsight AI Assistant](/ai-assistant/): overview information * [Using the AI Assistant](/using-the-ai-assistant/): understanding the AI’s capabilities - [Valsight MCP integration](/valsight-mcp-server/): connect an external AI client instead of chatting in the app --- # FAQ: Valsight MCP integration URL: https://docs.valsight.ai/frequently-asked-questions-valsight-mcp-integration/ Description: Frequently asked questions about the Valsight MCP integration — connecting an external AI client to Valsight, security, prerequisites, and what it can do. Common questions about the **Valsight MCP integration** — connecting your own external AI client to Valsight. This is the technical, external counterpart to the [in-app Assistant](/using-the-ai-assistant/); if you want to chat with the AI inside Valsight instead, see the [FAQ: AI Assistant](/frequently-asked-questions-valsight-ai-assistant/). **What is the Valsight MCP integration?** It lets you connect your own external AI client — such as Claude — to Valsight over the Model Context Protocol (MCP), an open standard for connecting AI clients to tools and data. The connected client can then explore and, in write mode, change your models from outside the Valsight app, always within your own permissions. **How is it different from the in-app AI Assistant?** The **in-app Assistant** is a conversational assistant you use inside Valsight, aimed at all users. The **MCP integration** lets you drive Valsight from your own external AI client or agent, and is aimed at technical users. Both build on the same model context and both act only within your Valsight permissions. **Which AI clients can I use?** Any AI client that supports MCP. There is no single, standard way to configure an MCP server, so the exact steps depend on the client — follow that client's own MCP setup instructions. Guides for specific clients may be provided over time. **How do I connect?** Point your AI client at your instance's MCP endpoint and sign in when prompted, using your normal Valsight login. There is no single, public endpoint: the address is specific to your Valsight instance. Your instance must also have the MCP integration enabled (see prerequisites). **What do I need before I can use it?** * Your Valsight instance must have the MCP integration **enabled**. It is a premium feature, opted into per customer (see "What does it cost?" below). * A compatible Valsight version — available from Valsight 7.3.0. * An AI client that supports MCP. **What does it cost?** The MCP integration is a premium feature, available from Valsight 7.3.0. Through **31 December 2026** it is included for all customers at no additional cost, so you can connect your own AI client, work with your real models, and see what it adds before deciding to keep it. From **January 2027** it becomes a paid add-on. It is opted into per instance and needs some setup, so it is not enabled by default. To turn it on, or to talk through whether it fits your team, write to or contact your Customer Success representative. **Is it secure?** You authenticate with your normal Valsight sign-in, and the integration acts only within your permissions — it cannot see or do more than you can. Each connection runs as a session whose scope you control: which projects it can touch, whether it is read-only or write, and whether it can see numeric values. Connections are only accepted for recognized Valsight instances, and activity is logged. **Can it change my models?** Yes, when the session is connected in **write mode**. You control the session's access level (read-only or write) and its data access (restricted or full), as well as which projects are in scope. Connect read-only if you only want it to explore. **How do I control what a session can do?** Session scope is set when you connect, and you can also steer it by asking the agent in plain language or through the session-management page. It covers the target instance, the projects in scope, the access level, and data access; deleting whole projects and changing access rights are separate, off-by-default options. **How long does a connection last?** A session ends after a period of inactivity, when access is revoked, or when an administrator ends it. Your Valsight sign-in stays valid for 12 hours, after which you sign in again. ## Related * [Valsight AI](/ai-assistant/): overview of both ways to use Valsight AI * [Valsight MCP integration](/valsight-mcp-server/): what it is, capabilities, and how to connect * [FAQ: AI Assistant](/frequently-asked-questions-valsight-ai-assistant/): questions about the in-app Assistant --- # Function catalog URL: https://docs.valsight.ai/function-catalog/ Description: The function catalog is the authoritative list of all functions you can use in node formulas. The function catalog is the **authoritative list of all functions** you can use in node formulas. Use this section to look up a function’s purpose, syntax, parameters, and examples. For operators such as `+`, `-`, `*`, `/`, and comparisons, see [Operators](/operators/). ## Start here if you want to: | If you | Go to | | ------------------------------- | ------------------------------------------ | | Look up a function by name | [All functions (A-Z)](/all-functions-a-z/) | | Find a function by what it does | [Browse by category](/browse-by-category/) | ## Related * [Formula basics](/formula-basics/): notation, quoting rules, constants, comments * [Operators](/operators/): arithmetic and comparisons used inside formulas * [Troubleshooting guide](/troubleshooting-guide/): dimensionality and missing value behavior --- # Functions & formulas URL: https://docs.valsight.ai/functions-formulas/ Description: This section explains how to write node formulas in the Function Editor, how to reference node values, combine them with operators, and use functions to calculate across multi-dimensional data. This section explains **how to write node formulas in the Function Editor**: how to reference node values, combine them with operators, and use functions to calculate across multi-dimensional data. Use this section to learn the core formula conventions and find the right function for your modeling task. ## Start here if you want to: | If you | Go to | | ------------------------------------------------- | ------------------------------------------------------------------- | | Learn the core syntax conventions | [Formula basics](/formula-basics/) | | Find the most-used functions | [Quickstart: 10 common functions](/quickstart-10-common-functions/) | | Write a simple calculation or condition | [Operators](/operators/) | | Look up a function by name, or browse what exists | [Function catalog](/function-catalog/) | | Diagnose unexpected behavior | [Troubleshooting guide](/troubleshooting-guide/) | ## Who this section is for This section is for users who work with formulas in the Function Editor, such as modelers and reviewers. If you mainly work with simulations and do not build or edit the underlying models, go to [Simulations & Analysis](/simulations-analysis/). --- # FV URL: https://docs.valsight.ai/fv/ Description: Calculates the future value of a recurring annuity investment at a set point in the future, based on an interest rate, number of recurring payments, payment amount, present value, and payment timing. **Category:** [Finance functions](/finance-functions/) ## Overview The **FV** function **calculates the future value of a recurring annuity investment** at a set point in the future. It is based on an interest rate, a number of recurring payments, the amount of individual payments, the present value and either ordinary annuity or annuity due (type) indicating whether payments are due at the beginning or the end of period. Use this function when you need to calculate how much a series of recurring payments will be worth at a future date given a fixed interest rate. ## Syntax `FV('Rate', 'Nper', 'Pmt' [, 'Pv' [, Type]])` ## Parameters | Parameter | Description | Type | Required | Default | | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | ------- | | **Rate** | The interest rate. | Node reference | Yes | -- | | **Nper** | Number of periods: the number of payments to be made. | Node reference | Yes | -- | | **Pmt** | Payment per period: the amount of each payment made. Payments/costs should ideally be entered as a negative number, for example `-500`, but this is not required. | Node reference | Yes | -- | | **Pv** | Present value: the current value of the annuity. | Node reference | No | `0` | | **Type** | Indicates when payments are due (`1` = payment at beginning of period / annuity due, `0` = payment at end of period / ordinary annuity). Must be written as a plain number, not in quotes and not as a node reference. | Number | No | `0` | ## Watch out * `'Pmt'` is the leading input node: its levels define the result's shape, and every other input is aligned to it. * Every other input may use only levels that also exist on `'Pmt'`. It may use fewer levels, but not a level that `'Pmt'` does not have. * On the levels it shares with `'Pmt'`, each input must cover the same level values, otherwise the rows do not line up and the function returns an error. * Each input can also be a single number. * Giving every input the same levels as `'Pmt'` skips an internal alignment step and improves performance. * If costs or payments are entered as positive numbers in your model, multiply the result by `(-1)`. ## Examples ### Future value of a recurring annuity This example calculates the future value of 5 annual payments of 500 at a 3% interest rate, with payments made at the end of each period (ordinary annuity). | Parameter | Value | | ------------------------------------------------------------------------------------------------------------- | ----- | | `Rate` (Interest Rate) | 0.03 | | `Nper` (Number of Periods) | 5 | | `Pmt` (Payment per Period) | -500 | | `Pv` (Present Value) | 0 | | `Type`
Payment at Beginning of Period (Annuity Due) = 1
Payment at End of Period (Ordinary Annuity) = 0 | 0 | **Formula:** `FV('Rate', 'Nper', 'Pmt', 'Pv', 0)` | FV Result | | --------- | | 2,654.57 | ## Related | Function | When to use instead | | ------------ | --------------------------------------------------------------------------------- | | [PV](/pv/) | When you need the present value of future cash flows instead of the future value. | | [NPV](/npv/) | When you need the net present value of irregular cash flows with a discount rate. | --- # Tutorial: Build a Valsight Project URL: https://docs.valsight.ai/getting-started/ Description: This tutorial shows how to build a complete Valsight project from scratch. This tutorial shows how to build a complete Valsight project from scratch: you will create a project, set up dimensions, upload data, build a driver model, simulate scenarios, and analyze the results. ![Overview diagram of a Valsight project's structure: Scenario Manager, Charts, Models, Dimensions, and Data sources](./images/project-overview-diagram.png) **What you will build:** A complete project, with dimensions and data sources feeding a driver model (`Revenue = Volume x Price`), a simulation scenario in the Scenario Manager, and charts to analyze the results. ## Before you begin * You need a Valsight account with permission to create projects. See [Access Rights](/access-rights/) if you are not sure what your role allows. * Budget around 45–60 minutes to complete all six parts. * No sample file is provided; you will enter the example data shown in each part yourself. ## Tutorial structure This tutorial is split into six parts. Each part builds on the previous one. | Part | You will learn how to… | | ----------------------------------------------------------------- | ------------------------------------------ | | [Part 1: Create a Project](/part-1-create-a-project/) | Create a project and set its time horizon. | | [Part 2: Set Up Dimensions](/part-2-set-up-dimensions/) | Create product and location dimensions. | | [Part 3: Upload Data](/part-3-upload-and-validate-data/) | Upload and validate your data. | | [Part 4: Build the Driver Model](/part-4-build-the-driver-model/) | Build the calculation logic. | | [Part 5: Simulate](/part-5-simulate/) | Set up and activate a simulation scenario. | | [Part 6: Analyze Results](/part-6-analyze-results/) | Visualize results with charts and tables. | --- # Glossary URL: https://docs.valsight.ai/glossary/ Description: A chart option that creates comparisons across a selected dimension (for example, years or scenarios) for the selected visualization. The technical terms used throughout Valsight, covering model building, workspace visualization, scenario management and dimension management. ## A **Aggregation**\ ***Model***\ Summarizing data across levels (for example, Month → Year). The levels used determine how values are combined, and the behavior can be controlled per node.\ See [Aggregation Settings](/aggregation-settings/). **Aggregation settings**\ ***Model***\ Node settings that define how aggregation behaves for display and for calculation. Display aggregation affects workspace visuals, while calculation aggregation affects model results.\ See [Aggregation Settings](/aggregation-settings/). **Alignment**\ ***Model***\ How values from different inputs are matched before a calculation is applied. Alignment is primarily driven by shared dimensions and levels.\ See [Formula basics](/formula-basics/). **Allow simulation**\ ***Model***\ A node setting that makes a node selectable for simulation changes. Only nodes with simulation allowed can be modified by assumptions and measures.\ See [Allow Simulation of Nodes](/allow-simulation-of-nodes/). **Annotation**\ ***Model***\ Contextual information attached to model elements to explain assumptions, decisions, or changes. Annotations improve interpretability without affecting results.\ See [Annotations](/annotations/). **Assumption**\ ***Scenario Manager***\ A bundled set of simulation changes that represent a presumption or view about the future. An assumption typically groups multiple line-items for a financial concept.\ See [Assumptions](/assumptions/). **Assumption categories**\ ***Project***\ Custom attributes defined per assumption to structure and filter assumptions. Categories are set up by administrators and use predefined value lists. Previously called assumption properties.\ See [Assumption Categories](/assumption-categories/). **Assumption group**\ ***Scenario Manager***\ A higher-level category used to organize line-items. It bundles multiple line-items under one assumption.\ See [Assumptions & Line-Items](/assumptions-line-items/). **Assumption Line-Item**\ ***Scenario Manager***\ A single change to the base data that affects exactly one node and is always non-destructive. Line-items are used to apply controlled adjustments while preserving original data.\ See [Line-items](/line-items/). ## B **Base**\ ***Scenario Manager***\ A line-item column that shows the node values from the underlying model scenario. Base values are read-only and represent the unmodified starting point.\ See [Line-Item Data & Details](/line-item-data-details/). **Baseline**\ ***Model***\ The model scenario used as the reference point for simulations and comparisons. It is the basis of all simulation scenarios and is not impacted by simulations.\ See [Baselines](/baselines/). **Baseline/Base Scenario/Default Scenario**\ ***Workspace***\ A special scenario that serves as the foundation for all simulations and remains unchanged by assumptions. It provides the stable reference for all scenario results.\ See [Working with different Model Baselines](/working-with-different-model-baselines/). **Bottom-Up Modeling**\ ***Model***\ A modeling approach where values are defined at a detailed level and aggregated upward. This supports traceability from drivers to totals. **Business Key**\ ***Project***\ A unique identifier for a project across the entire instance. Unlike the project name, it must be globally unique.\ See [Business Key](/business-key/). ## C **Calculated node**\ ***Model***\ Not a node type, but a way of describing a node whose value comes from a formula rather than from data input. Any standard node becomes one once it carries a formula.\ See [Define Calculations for a Node](/define-calculations-for-a-node/). **Calendar months**\ ***Project***\ An optional dimension ("CalendarMonth") with values 01–12 used to analyze seasonal effects across years. It differs from Month because it does not include the year.\ See [Calendar Months Dimension](/calendar-months-dimension/). **Change**\ ***Scenario Manager***\ A line-item column where simulation changes are entered and saved. The result is computed as Base + (Further effects, if present) + Change.\ See [Line-Item Data & Details](/line-item-data-details/). **Chart**\ ***Workspace/Sheets***\ A graphical representation of model or simulation values. Chart types determine how series are displayed for analysis and comparison.\ See [Chart Types](/chart-types/). **Chart filter**\ ***Workspace***\ A filter applied only to a single chart. It restricts chart content without changing other workspace objects.\ See [Chart Filter](/chart-filter/). **Compound Unit**\ ***Model/Workspace***\ A unit that relates two units to each other (for example, Quantity / Euro). It is commonly used for ratios such as prices.\ See [Units](/units/). **Configure axes**\ ***Workspace***\ Inspector functionality that defines what is shown on chart axes and in series. It controls which dimensionality is displayed in the visualization.\ See [Formatting Charts](/chart-configuration/). **Configure hierarchy**\ ***Dimension Management***\ A function to create new levels and adjust the ordering of levels within a dimension. It defines the hierarchical structure used across the project.\ See [Creating & maintaining dimensions](/creating-maintaining-dimensions/). **Configure submodels**\ ***Model***\ A configuration that links models into a structured system of submodels. It enables a driver structure and shared access to lower-level model data.\ See [Structure Driver Models](/structure-driver-models/). **Connector Color**\ ***Model***\ A setting that defines the color of the connector lines between connected nodes. It helps visually distinguish relationships in the model. **Consistency**\ ***Model***\ The property that results follow the same logic across all relevant dimensions and scenarios. Consistency is achieved through structured modeling rather than manual replication. **Create Comparison**\ ***Workspace***\ A chart option that creates comparisons across a selected dimension (for example, years or scenarios) for the selected visualization.\ See [Comparisons](/scenario-time-or-dimension-level-comparison-delta/). **Cross effects**\ ***Workspace***\ An interaction effect that occurs when multiple drivers change simultaneously and the combined impact is not simply additive. Cross effects are commonly shown in bridge charts.\ See [Bridges](/bridges/). **Cube**\ ***Model***\ The multi-dimensional data structure that every node holds. A cube is defined by its dimensions and levels; each value exists at a specific intersection across all included dimensions. Cube size is the total number of intersections and grows with the cross product of level members.\ See [Cubes](/how-cubes-work/). ## D **Data node**\ ***Model***\ A node type representing data input values, used to bring data into the model context. It is the entry point for connecting data sources. There is no relative variant.\ See [Creating Nodes](/creating-nodes/). **Data preview**\ ***Model***\ A preview of the values for the selected node in the model. It is used for quick validation and understanding of what data arrives.\ See [Data Preview of Nodes](/data-preview-of-nodes/). **Data Source**\ ***Overarching/Model***\ A source of uploaded or connected data used as input for modeling. It can be an uploaded file, manually entered tables, or an external database connection.\ See [Data Upload & Import/Export Overview](/data-upload-import-export-overview/). **Default Scale**\ ***Model***\ A node setting that defines a default scale used when visualizing the node in charts (for example, always show in millions). It standardizes chart readability.\ See [Default Scale Settings in Nodes](/default-scale-settings-in-nodes/). **Default scenario**\ ***Workspace***\ The chosen baseline that new simulation scenarios are based on in a workspace. It defines the baseline context for simulation changes.\ See [Scenarios](/scenarios/). **Dimension**\ ***Dimension Management/Model/Workspace***\ A core structural category such as Time, Location, or Product that organizes values. Dimensions contain one or more levels and define how data is sliced.\ See [How dimensions work](/how-dimensions-work/). **Dimension hierarchy**\ ***Dimension Management***\ The ordering of levels within a dimension from less detailed to more detailed. It defines how roll-ups and drill-downs are structurally interpreted.\ See [How dimensions work](/how-dimensions-work/). **Dimension management**\ ***Dimension Management***\ The area where dimensions, levels, and level values are created and maintained. It acts as central master data management for structure.\ See [Creating & maintaining dimensions](/creating-maintaining-dimensions/). **Driver**\ ***Model***\ A variable input that influences dependent values through model logic. Drivers make cause-effect relationships explicit.\ See [Structure Driver Models](/structure-driver-models/). **Driver tree**\ ***Model***\ A representation of a business model as cause-effect relationships between key figures. It maps interdependencies to explain how results are derived.\ See [Structure Driver Models](/structure-driver-models/). ## E **Expansion**\ ***Model***\ Creating values at a more detailed level from less detailed inputs. Expansion increases granularity while preserving structural rules.\ See [EXPAND](/expand/). ## F **Formula**\ ***Model***\ A calculation expression used to define cause-effect relationships between nodes. Formulas can include arithmetic operations and named functions and are written in the operation field.\ See [Formula basics](/formula-basics/). **Function editor**\ ***Model***\ The panel used to enter formulas and calculations for a node, with **Function** and **Data** buttons for inserting them. It supports comments using a hash sign (#) that do not affect logic.\ See [Define Calculations for a Node](/define-calculations-for-a-node/). ## G **Group assumption effects**\ ***Workspace***\ A setting on an assumption bridge that controls whether removed assumption or category groups appear separately. It is a chart setting, not a project setting, and is stored in the chart under the key `groupRemovedParametersSeparately`.\ See [Grouping Assumption Effects in Bridges](/grouping-assumption-effects-in-bridges/). **Group Key**\ ***Model***\ A setting that groups how effects are displayed in bridge charts. It allows multiple nodes to share the same grouping label in effect displays.\ See [Grouping Assumption Effects in Bridges](/grouping-assumption-effects-in-bridges/). ## H **Hide in workspace**\ ***Model***\ A node setting that removes the node from workspace selection and visualization. Hidden nodes remain part of model logic but are not exposed in workspaces.\ See [Advanced Node Settings](/advanced-node-settings/). **Hide outgoing connectors**\ ***Model***\ A node setting that hides connector lines leaving the node. It reduces visual clutter in complex model structures.\ See [Advanced Node Settings](/advanced-node-settings/). **Horizon level**\ ***Project***\ The time level that determines how horizon start and end are specified (for example, year vs. month). It does not limit the temporal detail available in modeling.\ See [Changing the Time Horizon](/changing-the-time-horizon/). ## I **Impact Proxy**\ ***Model***\ A model setting used to represent or proxy impacts for analysis. It supports clearer effect attribution where direct representation is not desirable. **Imported scenarios**\ ***Project***\ Fixed scenario values imported from external sources for comparison in charts. Imported scenarios cannot be changed and are used as reference benchmarks.\ See [Importing Scenarios](/importing-scenarios/). **Include in export**\ ***Model***\ A node setting that controls whether a node can be selected for scenario export. Nodes are exportable by default unless excluded.\ See [Export Manager](/export-manager/). **Inspector**\ ***Workspace/Sheets***\ A context-sensitive panel used to configure selected objects, especially charts. It is located on the right.\ See [Formatting Charts](/chart-configuration/). **Instance**\ ***Overarching***\ The technical environment where Valsight is installed and operated. Instance settings define the boundary for projects and administration. ## L **Level**\ ***Dimension Management/Model/Workspace***\ A layer within a dimension hierarchy that defines a degree of detail (for example, Year, Quarter, Month). Levels structure how aggregation and analysis behave.\ See [How dimensions work](/how-dimensions-work/). **Level value**\ ***Dimension Management/Model/Workspace***\ A specific member of a level that "fills" the level with concrete values (for example, 2022, 2023). Level values define the selectable members for analysis and data.\ See [How dimensions work](/how-dimensions-work/). **Line-item**\ ***Scenario Manager***\ The smallest element of a simulation that changes exactly one node's data. A line-item is always assigned to an assumption and changes simulation-enabled nodes only.\ See [Line-items](/line-items/). **Linked Levels**\ ***Dimension Management/Model/Workspace***\ Level values that are linked to values in another dimension. Linked levels support cross-dimensional mappings and consistent structural relationships.\ See [Linked levels](/linked-levels/). ## M **Manage Shared Scenarios**\ ***Workspace***\ The dialog for managing the shared scenarios within a project, including visibility and access. It provides an overview of scenarios shared by you or other users.\ See [Sharing Scenarios](/sharing-scenarios/). **Measure**\ ***Scenario Manager***\ A bundled set of consequences or actions that have an effect on a determined area. Measures represent planned interventions (for example, hiring, investing) rather than observations.\ See [Scenario Manager](/scenario-manager/). **Model**\ ***Model***\ A structured representation of relationships and calculations for a business or business area. A model contains nodes, can be split into submodels, and defines cause-effect logic.\ See [Models](/models/). **Model editor**\ ***Model***\ The view where model logic and calculations are defined using nodes and their connections. It represents the model visually and structurally.\ See [Model Editor UI](/model-editor-ui/). **Model graph**\ ***Model***\ A visual overview of models and their connections within a project. It supports understanding and navigating complex submodel structures. **Model horizon**\ ***Model***\ The time period applied in a model, defined by horizon start and end. It can differ from the project horizon, though it matches by default.\ See [Changing the Time Horizon](/changing-the-time-horizon/). **Model name**\ ***Model***\ A unique name for a model within a project. It is commonly structured with numeric prefixes to support sorting and clarity.\ See [Creating and Configuring Models](/creating-and-configuring-models/). **Model scenario/Baseline**\ ***Model/Workspace***\ A default data view in the model that serves as the basis for simulations. Models can contain multiple baselines to support scenario-specific logic.\ See [Working with different Model Baselines](/working-with-different-model-baselines/). **Model validation**\ ***Model***\ A model check that validates node calculations and formulas for correctness. It surfaces syntax or logic errors across the model and its submodels.\ See [Model Validation](/model-validation/). ## N **Node**\ ***Model***\ The smallest element of a model used to represent a key figure and its calculation logic. Nodes define cause-effect relationships through operations and can be of different types.\ See [Nodes](/nodes/). **Node editor**\ ***Model***\ The configuration area for a selected node where properties like name, unit, and settings are adjusted. It controls how the node behaves and is presented.\ See [Node Editor](/node-editor/). **Node ID**\ ***Model***\ A technical identifier that uniquely identifies a node in the system. It is used internally to reference the node reliably. ## O **Open**\ ***Workflow***\ A workflow status indicating that a step is available to be started. It represents the initial state before execution begins.\ See [Using Workflows (For Contributors)](/using-workflows-for-contributors/). **Operation per scenario**\ ***Model***\ A capability to define different logic per model scenario within the same node. It allows scenario-specific calculation behavior inside one model structure. ## P **Presentation**\ ***Workspace***\ A saved version of a workspace visualization that can be shared for viewing without project permissions. Presentations can include selected worksheets and support exporting to PDF.\ See [Using the Presentation Mode](/using-the-presentation-mode/). **Project**\ ***Overarching***\ A container that bundles models, data, dimensions, simulations, and visual outputs for a specific use case. It represents the organizational unit for planning work.\ See [Projects](/projects/). **Project horizon**\ ***Overarching***\ The time period applied to the project, defined by horizon start and end. It sets the default temporal scope across project elements.\ See [Changing the Time Horizon](/changing-the-time-horizon/). ## R **Reconfigure**\ ***Scenario Manager***\ A line-item action used to update or re-edit configuration such as filters or input mode. It is commonly used to resolve errors or refresh settings.\ See [Line-items](/line-items/). **Result**\ ***Scenario Manager***\ A line-item column that displays the computed simulation result (Base + Further effects + Change). Values entered here are not saved directly; only the implied change is saved.\ See [Line-Item Data & Details](/line-item-data-details/). ## S **Save as template**\ ***Workspace/Scenario Manager***\ A function that saves assumptions for reuse, including selected line-items and filters. It supports repeatable scenario setup.\ See [Assumption Templates](/assumption-templates/). **Scenario**\ ***Workspace/Scenario Manager***\ A representation of a possible future defined by a set of assumptions and measures. Scenarios are used to compare alternative developments.\ See [Scenarios](/scenarios/). **Scenario assumption**\ ***Workspace/Scenario Manager***\ A saved, uneditable bundle of active assumptions from a shared scenario. It enables sharing scenario logic across workspaces consistently.\ See [Sharing Scenarios](/sharing-scenarios/). **Scenario bridge**\ ***Workspace***\ A chart that explains differences between scenarios at a point in time by attributing impacts to assumptions and effects. It supports transparent scenario comparison.\ See [Scenario Bridges](/scenario-bridges/). **Scenario export**\ ***Workspace/Scenario Manager***\ An export of scenario results for selected nodes (for example, to Excel, CSV, or OData). It enables downstream reporting or integration with other systems.\ See [Export Manager](/export-manager/). **Scenario Manager**\ ***Workspace/Scenario Manager***\ The workspace area where scenarios, assumptions, and measures are defined and managed. It acts as the simulation cockpit for planning and analysis.\ See [Scenario Manager](/scenario-manager/). **Scenario selection**\ ***Scenario Manager***\ A line-item option that displays effects from other active simulations in the selected scenario. It introduces the "Further effects" component in the base-change-result logic. **Section/Divider**\ ***Model***\ A visual divider used to separate and organize nodes in the model editor. Sections support readability without affecting calculations.\ See [Creating Sticky Notes & Frames](/creating-sticky-notes-frames/). **Share**\ ***Scenario Manager – Scenario***\ A scenario action that bundles active assumptions into a shared, fixed scenario assumption. Shared scenarios can be reused across workspaces and users.\ See [Sharing Scenarios](/sharing-scenarios/). **Sheet**\ ***Workspace***\ A canvas for creating and arranging charts and other visualizations. Sheets structure analysis into tabs and can be selectively included in presentations. Called a worksheet in a few older dialogs.\ See [Visualizing Data](/visualizing-data/). **Sheet group**\ ***Workspace***\ A named group of sheets in the tab bar. Sheets are put into one with **Assign to group** and taken out with **Ungroup**.\ See [Workspaces](/workspaces/). **Shift**\ ***Scenario Manager***\ A feature that moves assumptions in time to earlier or later periods. It supports timeline adjustments without rebuilding line-items.\ See [Shifting Assumptions](/shifting-assumptions/). **Show data effects in bridges**\ ***Model***\ A setting that controls how data-driven changes appear in bridge visualizations. Effects can be shown as generic "Data" or attributed to specific nodes or group keys.\ See [Data Effects Display in Bridge](/data-effects-display-in-bridge/). **Simulation**\ ***Workspace/Scenario Manager***\ Calculating alternative outcomes by applying assumptions and measures on top of a baseline while using the same model logic. Simulations are non-destructive and dimension-consistent.\ See [Simulations & Analysis](/simulations-analysis/). **Simulation horizon**\ ***Workspace***\ The time period applied within a workspace simulation, defined by horizon start and end. It can differ from the project horizon, though it matches by default. **Simulation node**\ ***Model***\ A node type intended to be changed through simulations. It is selectable in the Scenario Manager when simulation is allowed.\ See [Allow Simulation of Nodes](/allow-simulation-of-nodes/). **Simulation scenario**\ ***Scenario Manager***\ A scenario created in the Scenario Manager that combines a selected model scenario with active assumptions and measures. It represents a specific simulated future state.\ See [Scenarios](/scenarios/). **Simulation UI**\ ***Overarching***\ The user-facing part of Valsight used for modeling, simulation, dimension management, and analysis. It is distinct from administrative configuration areas. **Simulation Workspace**\ ***Workspace***\ A sandbox environment built on a model to create simulation scenarios and analyze results. It supports comparing outcomes using charts and tables.\ See [Workspaces](/workspaces/). **Single Select**\ ***Model***\ A node selection mode where each node is selected individually. It is used when precise single-node selection is required.\ See [Model Editor UI](/model-editor-ui/). **Sort and Format**\ ***Workspace***\ Inspector options to adjust ordering, formatting, and styling for selected chart contents. It applies after content selection is defined (for example, via Configure axes).\ See [Formatting Charts](/chart-configuration/). **Standard node**\ ***Model***\ A node type that is not intended to be modified in simulations. It remains model-only and serves as structural or calculated logic.\ See [Allow Simulation of Nodes](/allow-simulation-of-nodes/). **Submodels**\ ***Model***\ Linked models that form a larger model structure with shared access to lower-level nodes and data. Submodels support clean decomposition of complex organizations and driver structures.\ See [Structure Driver Models](/structure-driver-models/). ## T **Template Manager**\ ***Template Manager***\ A feature that manages templates used for exporting scenarios. It defines which nodes are included in an export and how exports are structured.\ See [Template Manager](/template-manager/). **Templates**\ ***Template Manager/Workspace***\ Blueprints used to export scenario results for selected nodes. Templates standardize scenario exports across users and cycles.\ See [Template Manager](/template-manager/). **Time dimension**\ ***Dimension Management/Model/Workspace***\ The system-generated dimension that holds the periods of a project. Its levels and level values are derived from the project time horizon rather than maintained by hand.\ See [The time dimension](/time-dimension/). **Tree diagram**\ ***Workspace***\ A visualization of model logic starting from a selected root node. It helps analyze and trace how a final key figure is derived. **Tree Select**\ ***Model***\ A node selection mode that selects a node and all nodes downstream of it. It supports bulk selection of connected logic paths.\ See [Model Editor UI](/model-editor-ui/). ## U **Unit**\ ***Model/Workspace***\ A display setting that defines how a node's key figure is expressed (for example, EUR, units). Units standardize interpretation and visualization.\ See [Units](/units/). **Upload Data**\ ***Model***\ A function that updates or uploads data sources directly from the model editor. It supports refreshing existing data sources used by the model.\ See [Data Source Upload](/data-source-upload/). ## V **Validation node**\ ***Model***\ A specifically configured node used to validate model correctness. A validation result of 0 indicates valid logic, while non-zero indicates an issue.\ See [Validation Nodes](/validation-nodes/). **Validation Node Checkup**\ ***Model***\ A manual process to run validation nodes and verify model correctness. It must be executed actively and does not run automatically in the background.\ See [Validation Nodes](/validation-nodes/). **Variable**\ ***Model/Workspace/Scenario Manager***\ A project-wide quantity referenced in modeling and simulation, always starting with a $ sign. Variables can be numeric or non-numeric and support reusable logic.\ See [Project Variables](/project-variables/). **Variant**\ ***Workspace/Scenario Manager***\ A grouped variation of a single line-item used to test alternative changes under the same conceptual change. Variants improve Scenario Manager clarity and scenario usability.\ See [Line-Item Variants](/line-item-variants/). **Version**\ ***Overarching***\ The installed software release level of a Valsight instance. Versions introduce technical improvements and new features and can be checked in the application footer.\ See [Release Notes](/release-notes/). **Versioning**\ ***Scenario Manager***\ A concept for managing changes over time and tracking revisions in scenario configuration. It supports stable planning cycles and controlled evolution of assumptions.\ See [Versioning](/versioning/). **View**\ ***Scenario Manager***\ A line-item option that controls scaling, decimals, and visible columns for that line-item. It adjusts presentation without changing underlying logic.\ See [Line-Item Data & Details](/line-item-data-details/). ## W **Workflow**\ ***Workflow***\ A feature that structures and supports a multi-user planning process through defined steps. It standardizes execution and provides process visibility.\ See [Workflows](/workflows/). **Workflow run**\ ***Workflow***\ An instance of executing a workflow across its steps. It represents an active planning cycle using the defined workflow structure.\ See [Using Workflows (For Contributors)](/using-workflows-for-contributors/). **Workspace**\ ***Workspace***\ A simulation environment based on an underlying model where scenarios are created, analyzed, and compared. Workspaces combine Scenario Manager changes with visualizations on worksheets.\ See [Workspaces](/workspaces/). **Workspace filter**\ ***Workspace/Scenario Manager***\ A workspace-wide filter applied across the entire workspace, affecting all sheets, charts, scenarios and assumptions. It can be used to restrict scope or responsibility.\ See [Workspace Filter](/workspace-filter/). **Workspace validation**\ ***Workspace***\ A validation process that checks for technical, logical, and user-defined errors in a workspace. It supports reliable simulation execution and interpretation.\ See [Workspace Validation](/workspace-validation/). ## Y **YoY-bridge**\ ***Workspace***\ A year-over-year bridge chart comparing points in time within a scenario. It attributes changes over time to effects and assumptions for transparent analysis.\ See [Time Bridges](/time-bridges/). --- # Grouping Assumption Effects in Bridges URL: https://docs.valsight.ai/grouping-assumption-effects-in-bridges/ Description: Net an assumption's removed and added contributions into a single bar in a bridge, or draw them as two separate bars. When two scenarios differ in whether an assumption is active at all, a bridge has two contributions to draw for it: the effect of taking it out of the start scenario, and the effect of putting it into the end scenario. Those two can step through the chart as separate bars, or be netted against each other into a single bar. ## What it is **Group Assumption Effects** is a toggle in a bridge's settings. It decides which of the two you get: | Toggle | What the bridge shows | | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Off** | Two bars for an element whose contribution is both removed and added, with the removed one marked by a trailing `*`. A line-item's variants each get their own bar. | | **On** | One bar per element, netting its removed and added contributions against each other. A line-item's variants are combined into their line-item's bar. | The toggle does not decide whether the bridge steps by assumption or by line-item. That comes from what you put on the axis in **Configure Axes**. With the toggle off, the assumption *Volume* contributes two bars: `Volume *` for taking it out of the start scenario, and `Volume` for putting it into the end scenario. ![A bridge with two bars for the same assumption, labeled Volume with an asterisk and Volume](./images/5166563378.png) With it on, the two net into a single bar: ![The same bridge with the two Volume bars netted into a single bar](./images/5165907989.png) ## When to use it * The bridge has become long and hard to read because every assumption that switches on or off between the scenarios takes two bars. * You want the chart to show what an assumption is worth on balance, rather than the removal and the addition side by side. * A line-item has several variants and you want its total effect rather than one bar per variant. Leave it off when the point of the chart is how much of an assumption's effect comes from dropping it out of the start scenario and how much from adding it to the end scenario. ## Configuration 1. Select the bridge. The chart editor opens on the right. 2. Go to **Bridge Settings**. 3. Switch **Group Assumption Effects** on or off. ## Good to know * **It groups variants too.** When a bridge shows line-items with differing variants as deltas, rather than assumptions, the setting combines those variants into a single bar as well. * **It is a display setting.** Grouping changes how the effects are drawn, never how they are calculated. See [Assumption Effects](/assumption-effects/). * **On a time bridge only the variant grouping applies.** Both bridge types carry the toggle, but a time bridge compares a single scenario against its own baseline. Nothing is ever removed, so there is nothing to net and the `*` bars never appear there. What the toggle still changes on a time bridge is whether a line-item's variants are drawn as separate bars. ## Related * [Assumption Effects](/assumption-effects/): how the effect of an individual assumption is derived. * [Scenario Bridges](/scenario-bridges/): explain a difference between scenarios. * [Time Bridges](/time-bridges/): explain a difference between periods. * [Data Effects Display in Bridge](/data-effects-display-in-bridge/): the equivalent grouping for the model's own contribution. --- # GT (>) URL: https://docs.valsight.ai/gt/ Description: Checking whether one input is greater than another **Category:** [Logical functions](/logical-functions/) ## Overview The **GT** function checks whether **the matching row on the first input is greater than the matching row in the second input**; true (1) is returned, false (0) otherwise. An undefined value is treated as the number **0** in the comparison; it does not force the result to false. `GT(undefined, -100)` returns 1, because 0 is greater than -100. Use this function when you need a 1/0 flag to mark where one input is greater than another. ## Syntax `GT('Node1', 'Node2')` `'Node1' > 'Node2'` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | | **Node2** | Second input node. | Node reference | Yes | ## Examples ### Checking whether one input is greater than another This example compares two input nodes row by row. The result returns 1 where the first input is greater than the second and 0 otherwise. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 400 | | 2026 | 700 | | 2027 | 850 | | 2028 | 500 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 350 | | 2026 | 400 | | 2027 | 850 | | 2028 | 600 | **Formula:** `GT('A', 'B')` | Year | GT Result | | ---- | --------- | | 2025 | 1 | | 2026 | 1 | | 2027 | 0 | | 2028 | 0 | ## Related | Function | When to use instead | | ----------------- | ------------------------------------------------------------------------------------------------------- | | [GTE (>=)](/gte/) | When equality should also count as a match instead of requiring the first input to be strictly greater. | | [LT (<)](/lt/) | When you need to check whether one input is less than another instead of checking for equality. | | [EQ (=)](/eq/) | When you want to check for exact matches instead of a greater-than condition. | --- # GTE (>=) URL: https://docs.valsight.ai/gte/ Description: Checking whether one input is greater than or equal to another **Category:** [Logical functions](/logical-functions/) ## Overview The **GTE** function checks whether **the matching row on the first input is greater than or equal to the matching row in the second input**; true (1) is returned, false (0) otherwise. An undefined value is treated as the number **0** in the comparison; it does not force the result to false. `GTE(undefined, -100)` returns 1, and two undefined cells compare as 0 >= 0, which is also 1. Use this function when you need a 1/0 flag to mark where one input is greater than or equal to another. ## Syntax `GTE('Node1', 'Node2')` `'Node1' >= 'Node2'` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | | **Node2** | Second input node. | Node reference | Yes | ## Examples ### Checking whether one input is greater than or equal to another This example compares two input nodes row by row. The result returns 1 where the first input is greater than or equal to the second and 0 otherwise. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 400 | | 2026 | 700 | | 2027 | 850 | | 2028 | 500 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 350 | | 2026 | 400 | | 2027 | 850 | | 2028 | 600 | **Formula:** `GTE('A', 'B')` | Year | GTE Result | | ---- | ---------- | | 2025 | 1 | | 2026 | 1 | | 2027 | 1 | | 2028 | 0 | ## Related | Function | When to use instead | | ----------------- | ---------------------------------------------------------------------------------------------------------- | | [GT (>)](/gt/) | When equality should not count as a match and the first input must be strictly greater. | | [LTE (<=)](/lte/) | When you need to check the opposite direction and include equality for values that are less than or equal. | --- # Hiding a Project URL: https://docs.valsight.ai/hiding-a-project/ Description: To help declutter the project overview and settings pages, project admins can now hide old or unused projects. Hidden projects are removed from main lists but remain accessible. As a project admin, hide old or unused projects to declutter the Project overview and settings pages, then view or reveal them again when needed. ## Steps ### Hide a project 1. Go to the **Project Overview** page. 2. Locate the project you want to hide. 3. Click the project's **three-dot menu** (⋮). 4. Select **Hide**. ![image-20241217-134233.png](./images/5866061880.png) The project is removed from the main **Project Overview** list for all users, and from related settings pages, including Project Settings, Access Rights Settings, and Export Sharing pages. ### Access a hidden project Hidden projects remain accessible to users with the necessary permissions: 1. Go to the **Project Overview** page. 2. Click **Hidden** in the top-right corner. 3. Browse the list of all hidden projects (hidden by you or others). ![image-20241217-134327.png](./images/5866029109.png) You can still duplicate, open, and work on a hidden project as usual, but its project settings are not editable. ### Show hidden projects in other settings In settings pages where hidden projects are relevant (for example, Access Rights or Export Sharing), enable the **Show Hidden Projects** checkbox to display them in the current view. ### Reveal a hidden project 1. Go to the **Project Overview** page. 2. Click **Hidden** to show the hidden projects list. 3. Click the project's **three-dot menu** (⋮) and select **Show**. ![image-20241217-134350.png](./images/5866127417.png) ## What you have done * After hiding, the project no longer appears in the active **Project Overview** list or related settings pages. * After revealing, the project reappears in the active **Project Overview** list and all relevant settings pages for all users with access rights. ## Limitations * Hiding a project does not impact existing access rights. All users with access can still work on the project. * To prevent users from making changes to a project instead, lock it (see [Locking and Unlocking of Projects](/locking-and-unlocking-of-projects/)) or remove access rights for all current users (see [Access Rights Documentation](/access-rights/)). --- # Hochlaufkurven URL: https://docs.valsight.ai/hochlaufkurven/ Description: Hochlaufkurven [Valsight - Hochlaufkurven.pdf](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989761046_Valsight-Hochlaufkurven.pdf) [Product dim.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5990285336_Product-dim.xlsx) [LeadTime data.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5990383621_LeadTime-data.xlsx) [Hochlauf data.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5990318096_Hochlauf-data.xlsx) --- # How cubes work URL: https://docs.valsight.ai/how-cubes-work/ Description: Every node in a Valsight model holds its values as a cube, a multi-dimensional data structure where each value is identified by its exact position across al… Every node in a Valsight model holds its values as a cube, a multi-dimensional data structure where each value is identified by its exact position across all relevant dimensions. Understanding what a cube is explains how functions behave, why operations produce the results they do, and what “maximum cube size” means in practice. ## The core idea [How dimensions work](/how-dimensions-work/) explains how Valsight organizes data across dimensions. A cube is the actual structure that holds those values for each node. In a spreadsheet, data lives in rows and columns. Adding a third axis requires a new sheet, a lookup formula, or a pivot, and the structure fragments as complexity grows. In Valsight, all values for a node exist inside a single cube: a multi-dimensional space where each axis is a dimension. A single value is located by its exact position across all dimensions at once. The flat table and the cube hold exactly the same data, just organized differently. A row like “Year = 2025, Region = EMEA, Product = Truck, Fixed Cost = 40 €” becomes a single point inside the cube, located at the intersection of those three axes. ![Valsight\_Cube.PNG](./images/7007567911.png) This is not only a visual metaphor: it is the actual structure of every node’s output. When a formula calculates a result, the result is a cube. When a function filters, reshapes, or expands data, it operates on a cube and returns a cube with a defined shape. When the system warns about “maximum cube size,” it refers to the number of intersections in that result. The geometric name is intentional: with two dimensions, the structure is a flat table. With three, it becomes a cube. With more, the same principles extend beyond physical visualization. ## Key components * **Dimension**: One axis of the cube (e.g. Time, Region, Product). See [How dimensions work](/how-dimensions-work/) for levels, hierarchies, and structural rules. * **Intersection**: A single point in the cube, defined by one level value per included dimension. A value lives at exactly one intersection. * **Cube size**: The total number of intersections in a cube. In the worst case this equals the cross product of all level members across all dimensions; in practice, most real-world cubes are sparse. ## Why this matters Because every node produces a cube, Valsight can apply operations consistently across any combination of dimensions, without requiring separate formulas or sheets for each view. This enables: * **Consistent aggregation**: Values at any level can be rolled up without rebuilding logic. The hierarchy encodes the relationship once. * **Predictable alignment**: When two nodes are combined, alignment is always determined by their shared dimensions. There are no hidden joins or implicit matches. * **Defined function behavior**: Every function in Valsight has a defined effect on the cube’s shape. FILTER reduces it. ROLLUP aggregates it. IS\_NA and EXPAND can fully expand it. Knowing a function’s shape behavior is central to using it correctly. * **Diagnosable results**: Most unexpected outputs trace back to a shape mismatch: the result is too aggregated, too granular, or unexpectedly expanded. Thinking in cubes makes these issues identifiable. Understanding cube size also explains a class of performance constraints. Some functions, in particular IS\_NA and EXPAND, create a fully expanded cube, generating a value for every possible intersection. When dimensions are large, this can produce a result that exceeds the configured maximum cube size. This is a structural consequence of the data model, not a bug. ## Design principles * Keep cubes as sparse as possible. Real-world models rarely need full cross products; prefer functions that preserve sparsity over those that expand it. * Understand the output shape of each function before using it. Every function either preserves, reduces, or expands the cube in a specific, predictable way. * When diagnosing unexpected results, check the shape first: is the output missing dimensions it should have, aggregated too broadly, or larger than expected? * A cube’s size grows multiplicatively with dimension members. Adding a new level or expanding a dimension can have significant downstream effects on calculations that reference it. ## Example The diagram above shows a **Fixed Costs** node with three dimensions: Year, Region, and Product. The value at the intersection Year = 2025, Region = EMEA, Product = Truck is 40 €. The same cube also holds the value at every other intersection: EMEA / Car = 175 €, Americas / Truck = 95 €, Americas / Car = 320 €, all within the 2025 slice. The 2024 slice holds a separate set of values at the same region and product intersections (45 €, 190 €, 105 €, 360 € respectively). A formula combining this cube with another node (for example, a volume node with the same dimensions) would align automatically along the shared axes. The result is a new cube with the same shape, unless a reshaping operation changes it. If Fixed Costs is filtered to EMEA only using FILTER, the result is a smaller cube: same three dimensions, but only the EMEA intersections. If IS\_NA is applied to check for missing values, the result is a fully expanded cube covering all Year × Region × Product combinations, whether or not data originally existed at that intersection. ## Related * [How dimensions work](/how-dimensions-work/) * [Dimensions](/dimensions/) * [Limitations & Data Sizing Guidelines](/limitations-data-sizing-guidelines/) --- # How dimensions work URL: https://docs.valsight.ai/how-dimensions-work/ Description: Dimensions define how data is structured and explored in Valsight by organizing values across multiple axes. Dimensions define how data is structured and explored in Valsight by organizing values across multiple axes. Use this page to learn the vocabulary (dimension, level, level value, hierarchy) and the mental model behind how Valsight stores and aggregates data. For rules on designing a good dimension, see [Best practices for dimensions](/best-practices-for-dimensions/). ## The core idea Instead of storing data in rows and columns, Valsight organizes data in a **multidimensional space**. Each dimension represents one axis along which values can vary. A single value is defined by its exact position across all relevant dimensions at once, for example the intersection of **Time**, **Product**, and **Region** simultaneously. ![Valsight\_Cube-20260521-112407.PNG](./images/7006814268.png) The structure that holds these values for each node is called a **cube**. See [Cubes](/how-cubes-work/) for how it works and what it means for function behavior. ## Key components * **Dimension**: one axis of analysis (for example Time, Region, Product). * **Level**: a resolution within a dimension (for example Year, Quarter, Month). * **Level value**: a concrete member of a level (for example 2026, 2026-Q1, 2026-01). * **Hierarchy**: the aggregation relationship between levels. ![Screenshot 2026-05-21 132549-20260521-112549.png](./images/7005306962.png) ## Why this matters Dimensions are referenced by every subsystem in Valsight that handles data: * **Data sources** are validated against dimensions on upload. Columns must match level names; values must match existing level values. * **Nodes** hold cubes shaped by dimensions, and formulas operate on those cubes, f.e. `EXPAND(0, "Year", "Region")` or `FILTER('Sales', "Region", ["EMEA", "APAC"])`. * **Scenarios and assumptions** scope their changes to dimensional slices. * **Charts** use dimensions on axes and as filters. * **Filters** at workspace, worksheet, perspective, and chart level can filter on dimension values. Hierarchical structure means a value tracked at the granular level (2026-01) rolls up consistently through its hierarchy (2026-Q1, 2026), and dimension design decisions ripple across the entire project. ## Related * [Cubes](/how-cubes-work/): the structure that holds dimensional values for each node * [The time dimension](/time-dimension/): the one dimension Valsight generates for you * [Best practices for dimensions](/best-practices-for-dimensions/): MECE, design principles, and limitations * [Creating dimensions](/creating-maintaining-dimensions/): setting up a dimension end to end * [Getting started: Build a Valsight Project](/getting-started/): a walkthrough that shows dimensions being created and used end to end --- # IF URL: https://docs.valsight.ai/if/ Description: The IF function evaluates a condition and returns one value when the condition is true and another when it is false. For every row of the input, the condition is evaluated independently. **Category:** [Logical functions](/logical-functions/) ## Overview The **IF** function **evaluates a condition and returns one value when the condition is true and another when it is false.** For every row of the input, the condition is evaluated independently. Use this function to implement business rules such as thresholds, caps, floors, or other conditional logic. ## Syntax * `IF(Condition)` returns the condition's value where true and no value where false. * `IF(Condition, ValueIfTrue)` returns ValueIfTrue where true and no value where false. * `IF(Condition, ValueIfTrue, ValueIfFalse)` returns one value for true and another for false. **Example usage:** `IF('Margin' < 0, 0, 'Margin')` ## Parameters | Parameter | Description | Type | Required | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- | | **Condition** | A node evaluated to true or false. `0` is interpreted as false; all other values as true. Comparisons can be configured with logical functions. | Node reference | Yes | | **ValueIfTrue** | Value returned when the condition is true. | Node reference or number | No | | **ValueIfFalse** | Value returned when the condition is false. | Node reference or number | No | ## Building conditions Conditions can be written as operators or with logical functions. Most users write the operator form directly in formulas. | Operator | Function | Meaning | | -------- | ----------------- | --------------------- | | `=` | [EQ (=)](/eq/) | equal | | `!=` | [NEQ (!=)](/neq/) | not equal | | `>` | [GT (>)](/gt/) | greater than | | `>=` | [GTE (>=)](/gte/) | greater than or equal | | `<` | [LT (<)](/lt/) | less than | | `<=` | [LTE (<=)](/lte/) | less than or equal | | `&&` | [AND (&&)](/and/) | both conditions true | | `\|\|` | [OR (\|\|)](/or/) | at least one true | | | [NOT](/not/) | invert condition | | | [IS\_NA](/is-na/) | value is undefined | For details and pitfalls, see [Comparisons & boolean operators](/comparisons-boolean-operators/). ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Dimensionality | Union of all input dimensionalities. Per dimension, the finest granularity across the condition, ValueIfTrue, and ValueIfFalse is used. | | Row count | Depends on the form used. With all 3 arguments, the output contains one row per condition row (true rows get ValueIfTrue, false rows get ValueIfFalse). With 1 or 2 arguments, rows where the condition is false are dropped (become N/A). | | Values | The condition is evaluated independently for each row | ## Watch out * When all three arguments are provided, if ValueIfTrue or ValueIfFalse has finer dimensionality than the condition, both must have the same dimensionality. This check does not apply to the 1- or 2-argument form. * 0 is interpreted as false, any other value as true. * When IF returns N/A, the cell appears empty in tables and is excluded from charts. This is different from returning 0. N/A means "no value exists," while 0 is a real numeric value. ## Examples ### Dividend payout Dividends are only paid in years with **positive net income**. The payout equals **50 % of net income**. **Input node:** `'Dividend Payouts / Net Income'` | Value | | ----- | | 50% | **Input node:** `'Net Income'` | Year | Value | | ---- | ----- | | 2025 | -30 | | 2026 | 20 | | 2027 | -10 | | 2028 | 0 | | 2029 | 100 | **Formula:** `IF('Net Income' > 0, 'Net Income' * 'Dividend Payouts / Net Income', 0)` | Year | IF Result | | ---- | --------- | | 2025 | 0 | | 2026 | 10 | | 2027 | 0 | | 2028 | 0 | | 2029 | 50 | Dividends are only paid in years with positive net income. Example calculations: * 2026 → 20 × 50 % = 10 * 2029 → 100 × 50 % = 50 ### Floor at zero Negative margins should be reported as 0. **Input node:** `'Margin'` | Year | Value | | ---- | ----- | | 2025 | 15 | | 2026 | -8 | | 2027 | 22 | | 2028 | -3 | **Formula:** `IF('Margin' < 0, 0, 'Margin')` | Year | IF Result | | ---- | --------- | | 2025 | 15 | | 2026 | 0 | | 2027 | 22 | | 2028 | 0 | ### IF used as a condition check When only the condition is provided, IF returns 1 when the condition is true and no value (N/A) when it is false. **Input node:** `'Revenue'` | Year | Revenue | | ---- | ------- | | 2025 | 800 | | 2026 | 1200 | | 2027 | 1500 | | 2028 | 600 | **Formula:** `IF('Revenue' > 1000)` | Year | IF Result | | ---- | --------- | | 2026 | 1 | | 2027 | 1 | In this example, the comparison `'Revenue' > 1000` evaluates to 1, which is what IF returns. If you use `IF('Revenue')` directly, it returns Revenue's own value for non-zero rows. This pattern is useful when creating **binary helper tables** or **flags** for further filtering or visualization. ### Using IF(Node) to remove zero values When a node itself is used as the condition, IF checks whether the value is true (non-zero) or false (zero). Because IF interprets 0 as false, those entries become N/A in the result. **Input node:** `'Revenue'` | Year | Revenue | | ---- | ------- | | 2025 | 0 | | 2026 | 120 | | 2027 | 0 | | 2028 | 300 | **Formula:** `IF('Revenue')` | Year | IF Result | | ---- | --------- | | 2026 | 120 | | 2028 | 300 | This technique replaces zeros with N/A values, which can help avoid misleading totals and reduce visible rows in tables and charts. ## Related | Function | When to use instead | | --------------------------------- | ---------------------------------------------------------------------------- | | [FILTER](/filter/) | Removes non-matching rows entirely instead of returning an alternative value | | [TRUE](/true/) / [FALSE](/false/) | Boolean constants usable inside conditions | --- # Images URL: https://docs.valsight.ai/images/ Description: Add an image tile to a worksheet, for a logo, a diagram or any other picture. An image tile places a picture on a worksheet, next to your charts. Use it for a logo, a diagram, or anything else that gives a sheet context without being data. ## What it is An image tile starts empty. You add it like any other tile, then upload a picture into it. The tile holds one image, and it can be moved and resized like a chart. ![An empty image tile on a sheet, with its Upload Image button](./images/5094193245.png) ## When to use it * You want a logo or a title graphic on the sheet you present from. * You want a diagram that explains something the charts cannot, such as a process or an org structure. * You want a picture as a visual anchor on a dashboard. For text rather than a picture, use a text tile instead. Both are listed under **Others** in the chart type selection. See [Chart Types](/chart-types/). ## Configuration 1. Open the sheet you want the image on. 2. Add a chart and find the **Image** option under the **Others** group of the selection. 3. The selection closes and an empty tile appears on the sheet. 4. Click **Upload Image** in the middle of the tile. 5. Choose a file from your computer. ![The image upload dialog](./images/5094193275.png) | Requirement | Value | | --------------------- | ----------------------------------------------------------- | | **Formats** | `.png`, `.jpg`, `.jpeg` | | **Color space** | RGB. CMYK is not supported. | | **Maximum file size** | 1 MB | | **Resizing** | Images wider than 3840px (4K) are scaled down to that width | ## Good to know * **A CMYK file will not upload**, even in a supported format. Convert it to RGB first. This catches print-ready logos most often. * **1 MB is the hard limit**, so a large photograph usually needs compressing before it will upload. * **GIF is not supported.** The file picker offers PNG, JPG and JPEG only. Convert an animated GIF to a still PNG first. * **Images are not data.** Nothing in an image tile updates when a scenario or the model changes. ## Related * [Chart Types](/chart-types/): the other tiles you can place on a worksheet. * [Using the Presentation Mode](/using-the-presentation-mode/): sharing a finished sheet as a static snapshot. --- # Importing Scenarios URL: https://docs.valsight.ai/importing-scenarios/ Description: Scenarios are dynamically calculated based on data, and model logic and always reflect their active assumptions. Every scenario you create in a workspace is … Scenarios are dynamically calculated based on data, and model logic and always reflect their active assumptions. Every scenario you create in a workspace is a dynamically calculated scenario. In contrast, ***imported scenarios*** are fixed data points that are uploaded to a project. Their values are displayed exactly as uploaded and will not change. For limitations with imported scenarios, please see the notes at the bottom. ## Downloading existing scenarios You can now download the data for existing scenarios from the Scenario Manager. In order to do that, go to the workspace, click on the scenario menu in the Scenario Manager and click on "**Export as → XLSX"**. ![Screenshot 2020-03-04 at 10.04.09.png](./images/5094191234.png) ## Creating imported scenarios Imported scenarios are created in the context of a project using the project settings page. ![image2020-3-13\_9-31-11.png](./images/5094190272.png) ![imported\_scenarios\_section.png](./images/5094193720.png) On the **imported scenarios** setting page, you can rename/create/delete scenarios or upload data. The names of imported scenarios have to be unique per project. Data is provided by uploading an XLSX file. On upload, the data will be matched and validated against the project dimensions (similar to the upload of data sources). On import, every sheet will be matched to a node in the project. > **The workbook must contain a sheet named `Metadata`.** Without it the upload stops with ‘The mandatory "Metadata" sheet is not present in the uploaded file.’ and nothing is mapped at all. The sheet needs the three columns **Sheet**, **Model** and **Node**; a missing one is reported the same way. **Special Function**, **Sheet 1** and **Sheet 2** are optional and are used for ratio nodes, described below. ## Mapping manually to existing nodes The mapping is performed using the sheet name as "'modelname'.'nodename'". If names are too long or use special signs, the mapping can be overwritten by providing a comment in the rows of the sheet that will then be used for the mapping. See the appended excel file for an example of what the comment should look like: ![Screenshot 2020-03-04 at 10.09.32.png](./images/5094191239.png) The column for the value of the node needs to match one of the following names: 'AMOUNT', 'MEASURE', 'VALUE', 'MEASURE\_DISTRIBUTION' ![image2020-1-15\_14-41-11.png](./images/5094216138.png) ## Checking the mapping before the import Before the import is committed, the wizard shows a **Check Result** table with one row per sheet and column, giving the check result, the sheet and the column. Each entry carries one of five states: * **Existing:** the sheet or column was matched. * **Added** and **Removed:** the sheet or column is new in this upload, or was present in the previous one and is gone. * **Unmatched:** the sheet could not be matched to any node. * **Ignored:** the column is not used. Each entry explains itself on hover, with ‘This was recognized as a measure column’, ‘This could not be recognized as a measure or a level’ or ‘This could not match with any node’, and the counters above the table read ‘{n} unmatched sheet(s) found’ and ‘{n} unrecognized column(s) found’. This is the screen to work from when a mapping does not come out as expected. ## Using imported scenarios in charts Imported scenarios are displayed next to normal scenarios when configuring charts with the annotation "imported". They can be used in any other scenario and their data will be displayed in charts. However, as data is not dynamically calculated, imported scenarios do not support the calculation of assumption effects or assumption bridges. ![Screenshot 2020-01-15 at 14.42.59.png](./images/5094216162.png) ## Importing scenarios from another project To export from one, and import in the other: You can export a scenario from another project and import it as an imported scenario. This can be helpful to add comparisons, e.g. with a forecast or previous plan. In order to export the source scenario, open the project and navigate to the Scenario Manager in a simulation workspace containing the scenario to be exported. Open the context menu of the scenario by clicking the more (...) icon next to the scenario name and choosing "**Export as → XLSX**". This will generate and download an XLSX file with one sheet per node. As a next step, you can now create a new imported scenario in your current project and upload the exported data as described above. ![image2020-1-15\_14-35-41.png](./images/5094215886.png) Potential challenges when importing data from other projects: * Node names might have changed between the projects. You can map the names to the new project structure by replacing the old name in the exported XLSX file (sheet names and the name comment in cell A1). * Dimensions might have changed between the projects. If dimension or level names have changed, the import will not match the information to the respective dimensions and the data can not be analyzed using the dimension information. If values do not match, the upload will fail with errors that have to be resolved by replacing the old dimension values in the exported XLSX file with the new values matching the current project dimensions. ## Ratio nodes A node that is a ratio can be imported as a ratio instead of as pre-divided values. In the `Metadata` sheet, set **Special Function** to `RATIO` on that row and name the numerator and denominator sheets in **Sheet 1** and **Sheet 2**. Valsight then keeps the two inputs and divides them at the level being queried, so the ratio aggregates correctly rather than being fixed at the level it was imported on. `RATIO` and an empty cell are the only values **Special Function** accepts. ## Limitations Imported scenarios are pre-calculated and should always show the numbers independent of the project where they are imported in. * Aggregation settings of nodes are currently not part of imported scenarios and the nodes setting of the current model is used. * Imported scenarios do not contain assumptions and can therefore not be used to analyze assumption effects (e.g. in bridges). --- # Information Security & Availability Commitment / TISAX URL: https://docs.valsight.ai/information-security-availability-commitment-tisax/ Description: At Valsight, protecting sensitive data and ensuring uninterrupted service is not just a compliance requirement. It’s part of our DNA. At **Valsight**, protecting sensitive data and ensuring uninterrupted service is not just a compliance requirement: it’s part of our DNA. We have achieved **TISAX AL3** compliance for both **Information Security (Very High)** and **Availability (Very High)**. **TISAX** (Trusted Information Security Assessment Exchange) is the automotive industry’s security standard, managed by the ENX Association and based on the ISO 27001 framework. It incorporates all the core principles of ISO 27001 **and** adds sector-specific requirements for confidentiality, integrity, and availability, especially for environments where information is highly sensitive and uptime is mission-critical. ## What “TISAX AL3 Very High Protection Needs & Very High Availability” means for you: * **Highest assurance level** – Required for projects involving strictly confidential and business-critical data. * **Very High Protection Needs** – Strong encryption, multi-factor authentication, and rigorous physical & logical access control. * **Very High Availability** – Redundant systems, rapid disaster recovery, and 24/7 monitoring to minimize downtime. * **Trusted Supply Chain** – Security standards extend to our partners and service providers. While ISO 27001 is recognized globally as the baseline for information security management, **“TISAX AL3 Very High Protection Needs & Very High Availability” goes further** by tailoring and extending these controls to meet the automotive industry’s most demanding security and availability requirements. This means that our TISAX accreditation not only meets but **surpasses the scope of ISO 27001** for our operational context. ## ISO 27001 vs. TISAX AL3 (Very High Protection Needs & Very High Availability) | Feature / Scope | ISO 27001 | TISAX AL3 (Very High) | | ----------------------------- | ---------------------------------------- | ----------------------------------------------------------------- | | **Framework Basis** | Generic, applicable to all industries | Based on ISO 27001, extended for automotive | | **Assessment Focus** | Confidentiality, integrity, availability | Confidentiality, integrity, availability with stricter thresholds | | **Assurance Level** | Defined by organization’s risk analysis | Fixed highest level (AL3) for very high-risk scenarios | | **Availability Requirements** | Determined by risk assessment | Very high uptime, redundancy, rapid recovery | | **Supplier Requirements** | General due diligence | Strict supplier and partner compliance | | **Recognition** | Global, cross-industry | Industry-specific, required by major automotive OEMs | | **Security Rigor** | High | Higher – supersedes ISO baseline for covered areas | --- # Input Tables URL: https://docs.valsight.ai/input-tables/ Description: Enter values directly into a table on the worksheet and see the effect on your scenario without leaving the sheet. An input table brings simulating and viewing together: values are typed straight into a table on the worksheet and the effect shows up immediately, with no switching between screens. ## What it is An input table looks like an ordinary table, but it has an **Input Data** mode. In that mode the cells accept typed values, and saving them applies the change across your scenario. ![An input table showing editable values per region, engine type and year](./images/5937365006.png) Each input table edits one line-item, in one of two views: | View | What you type | | --------------- | -------------------------------------------------- | | **Change View** | Relative changes, for example a percentage uplift. | | **Result View** | Absolute values, which replace what is there. | ## When to use it * You want a reader to try their own numbers without opening the Scenario Manager. * You want to enter many values at once, which is faster in a grid than with sliders. * You want to set a total that other tiles then divide up, for example one feeding a [split slider](/split-sliders/). Use a **[slider](/sliders/)** instead for a single value that is better dragged than typed, and a plain **table** when readers should only read the numbers. ## Configuration 1. Click **+ Chart** in the workspace. 2. Go to the **Simulations** category and select **Input Table**. ![The Simulations category with Input Table in the chart type selection](./images/5937463312.png) 3. Choose the **Line Item** to edit, and the **variant** to modify. ![The input table configuration, with the line-item and variant selected](./images/5936676877.png) 4. Edit the **Table title** if you want something other than the proposed one. 5. Choose **Change View** or **Result View**. **Change View** is preselected for an input table. ![An input table in Result View, showing absolute values](./images/5936676883.png) 6. Select the **scenario** the table writes to. **Create** stays disabled until the variant, the view and the scenario are all chosen. 7. Optionally apply **filters** to narrow the table to the rows that matter. A filter icon appears when you hover over a filtered table. ### Entering values 1. Hover over the input table tile and click **Input Data** in the top right corner. 2. Type values into the cells to test an assumption. ![Typing a value into an input table cell](./images/5937463306.png) 3. Click **Save** to apply the change across the scenario. Every linked table updates automatically. ## Good to know * **What you type depends on the view.** In **Change View** a `10` is a relative change; in **Result View** the same `10` is an absolute value. Check which view a table uses before entering numbers. * **Nothing is applied until you save.** Values typed in **Input Data** mode take effect on the scenario only when you click **Save**. * **A table can be maximized while you work.** Expanding it for easier entry does not lose what you have typed. * **Perspective and sheet filters apply.** They adjust the data shown in the table automatically, so the rows you see may depend on the sheet's current perspective. * **The table can be pivoted.** Once the tile exists, the **Pivot Table** button in the chart editor rearranges which dimensions sit in rows and which in columns. Putting time in the columns is what makes bulk entry, and pasting from a spreadsheet, workable. * **If the line-item's dimensionality changes, the table stops loading.** The tile then reports that the dimensionality of the chart and the line-item differ, and offers an **Adjust to line-item** button that rebuilds the table against the line-item's current shape. Rebuilding discards the filters and pivot layout on that tile, so expect to set those again. ![An input table maximized on the worksheet](./images/5937365000.png) ## Related * [Sliders](/sliders/): drag a single line-item's value instead of typing it. * [Split Sliders](/split-sliders/): redistribute a total across its parts while the total stays fixed. * [Chart Types](/chart-types/): the other tiles you can place on a worksheet. --- # Install an Evaluation Version on Windows URL: https://docs.valsight.ai/install-an-evaluation-version-on-windows/ Description: The following document describes how to install an evaluation version of the product on Windows. Windows is not supported for production use. For testing purposes, Valsight can be installed on any Windows 11 computer with at least 4 GB RAM (8 recommended). *Important: This page describes how to install an evaluation version. Windows is not a supported operating system for production use — see [On-Premise Installation Guide](/on-premise-installation-guide/) for a supported production setup on Linux.* Valsight does not ship with a Java runtime. Install 64-bit OpenJDK 21 and set the `JAVA_HOME` environment variable to its installation directory (the path must not include the `\bin\` folder). The startup script refuses to start on any other Java major version. Unzip the ZIP file at a location without spaces, e.g. c:\valsight. In the \bin directory, a .bat file can be found - start it. The application starts with a blank console window. The start takes a few minutes. ![valsight-server - Shortcut 2018-02-16 14.47.29.png](./images/5094190692.png) After the start, the application responds with "Grails application running on ..." You can now point your browser to localhost:8080 (default) to access the application. ![Desktop 2018-02-16 14.50.40.png](./images/5094190667.png) After logging in with the default admin:admin account, you need to provide a license file. *Tip: The application runs with an integrated H2 SQL database, and all configuration is stored in the* `\db` *folder. To migrate content from an evaluation instance to a productive instance, use the [export and import functions](/data-import-export/) for the projects you want to migrate.* ## Backup of the POC instance Our recommendation to store a backup of the POC instance is as follows: 1. Stop the Valsight server by closing the cmd-window (Important, otherwise the open database file cannot be backed up correctly) 2. Zip the entire Valsight folder (e.g. c:\valsight) by right-click, send to compressed folder. If the ZIP file cannot be written on c:\ Windows will ask to create the file on the desktop. 3. Rename the file to contain the current date and time. (e.g. "201812040815valsight.zip") 4. Store the file on a central file share to prevent data loss in case of hardware problems of the laptop We recommend to take a daily backup during the evaluation phase. --- # Introduction to Valsight API URL: https://docs.valsight.ai/introduction-to-valsight-api/ Description: Every part of the Valsight server can be accessed via a REST-based API. Every part of the Valsight server can be accessed via a REST-based API. Navigate to the *REST API Browser* in the help section of the Admin Interface to find possible operations and explanation on their usage. ![image-20260521-144740.png](./images/7008059414.png) --- # IRR URL: https://docs.valsight.ai/irr/ Description: Internal rate of return (IRR) is a metric of profitability for potential investments. It is the discount rate that sets the net present value of all future cash flows of the investment equal to zero, found using numerical iteration. **Category:** [Finance functions](/finance-functions/) ## Overview The **IRR** function **calculates the internal rate of return** ([IRR](https://en.wikipedia.org/wiki/Internal_rate_of_return)), a metric of profitability for potential investments. Internal rate of return is a discount rate that sets the net present value ([NPV](https://en.wikipedia.org/wiki/Net_present_value)) of all future cash flows of the investment equal to zero. An approximate solution is found using numerical iteration. Use this function when you need to find the discount rate at which an investment's cash flows break even (NPV = 0). ## Syntax `IRR('Node' [, Guess])` ## Parameters | Parameter | Description | Type | Required | Default | | --------- | --------------------------------------------------------------------------------------------- | -------------- | -------- | ------- | | **Node** | Yearly cash flows. At least one of the cash flows must be negative and at least one positive. | Node reference | Yes | -- | | **Guess** | A first guess at the rate. | Number | No | `10%` | ## Examples ### IRR of a project with mixed cash flows This example calculates the internal rate of return for a project with an initial investment and subsequent positive cash flows. **Input node:** `'CF'` | Year | Value | | ---- | ------ | | 2025 | -10000 | | 2026 | 1155 | | 2027 | 5000 | | 2028 | 7000 | Our goal is to find a discount rate with which the discounted cash flows sum up to zero: ![image2018-7-24\_10-39-30.png](./images/5094190292.png) **Formula:** `IRR('CF')` | Year | IRR Result | | ---- | ---------- | | 2027 | -23% | | 2028 | 12% | The IRR function tells us the rate is 12%. The result for cash flows up to year 2027 is not interesting for us and can be filtered out with the [FILTER](/filter/) function. ## Related | Function | When to use instead | | -------------- | ---------------------------------------------------------------------------------------------- | | [NPV](/npv/) | When you need the net present value at a known discount rate rather than solving for the rate. | | [CAGR](/cagr/) | When you need compound growth over N periods rather than the break-even discount rate. | --- # IS_NA URL: https://docs.valsight.ai/is-na/ Description: The IS_NA function returns 1 for any values that are undefined (not available) in the input and 0 for any values that exist. The result covers the full cross product of all dimension levels, not just the rows present in the input. **Category:** [Logical functions](/logical-functions/) ## Overview The **IS\_NA** function **returns 1 for any values that are undefined (not available) in the input** and 0 for any values that exist. The result covers the full cross product of all dimension levels, not just the rows present in the input. Use this function when you want to detect undefined values explicitly before they cause unexpected empty results in downstream logic. ## Syntax `IS_NA('Node')` **Example usage:** `IS_NA('Revenue')` ## Parameters | Parameter | Description | Type | Required | | --------- | ---------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------------------------------------------------------------ | | Dimensionality | Same dimensions as input. | | Values | **1** where the input is undefined (N/A). **0** where the input has a value. | | Row count | **Expanded** to the full cross product of all level values in the input's dimensions. This is typically larger than the input. | ## Watch out * IS\_NA **expands to the full cross product** of all level values. This can produce a very large result and may hit the maximum cube size. Use with caution on nodes with many dimension levels. * IS\_NA returns 1 for **undefined** intersections, not for zero values. A value of 0 is defined and returns 0, not 1. * Unlike [TRUE](/true/) and [FALSE](/false/), IS\_NA does not just operate on existing rows. It creates rows for every possible combination of level values to check which ones are missing. ## Examples ### Detecting undefined values This example shows IS\_NA returning 1 where the input is undefined and 0 where a value exists. Note that 0 is a defined value and returns 0. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 400 | | 2026 | 0 | | 2027 | 850 | | 2028 | | **Formula:** `IS_NA('A')` | Year | IS\_NA Result | | ---- | ------------- | | 2025 | 0 | | 2026 | 0 | | 2027 | 0 | | 2028 | 1 | Year 2026 has a value of 0 (which is defined), so IS\_NA returns 0. Year 2028 has no value at all, so IS\_NA returns 1. ### Multi-dimensional expansion IS\_NA expands to all possible level value combinations. If some products are missing data in certain years, IS\_NA flags exactly those intersections. **Input node:** `'Sales'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | A | 100 | | 2025 | B | 200 | | 2026 | A | 150 | Product B has no data for 2026. **Formula:** `IS_NA('Sales')` | Year | Product | IS\_NA Result | | ---- | ------- | ------------- | | 2025 | A | 0 | | 2025 | B | 0 | | 2026 | A | 0 | | 2026 | B | 1 | IS\_NA creates the full cross product (2 years x 2 products = 4 rows) and marks the missing intersection (2026, B) with 1. ## Related | Function | When to use instead | | --------------------------------------- | ---------------------------------------------------------------------------------------------- | | [FALSE](/false/) | When you need a constant 0 for defined values instead of detecting missing ones. | | [TRUE](/true/) | When you need a constant 1 for defined values instead of marking undefined ones. | | [FILLMISSING](/fillmissing/) | When you want to fill missing values with a default instead of just detecting them. | | [FILLMISSING\_LAST](/fillmissing-last/) | When you want to fill missing values with the last given value instead of just detecting them. | --- # KPI Charts URL: https://docs.valsight.ai/kpi-charts/ Description: Show a single key figure as one large number, optionally with a reference value and a comparison. A KPI chart displays one key figure as a single large number with its unit, so the figure that matters is readable at a glance rather than being read off an axis. ## What it is A new KPI chart uses the first two years of your project horizon as its values, and **Year** as its level. Any other level of your dimensionality can be chosen instead, under **Level** in the chart editor. Of the two level values, the **primary** one is displayed large in the middle of the chart and the **secondary** one small in the lower left. That arrangement is the point: the primary value is the KPI, and the secondary one is context for it. The default order emphasizes the most recent year. ![A KPI chart showing one large figure with a reference value below it](./images/5310382130.png) ## When to use it * One number is the message, for example this year's gross profit or a CO2 total. * You want that number readable from across a room when presenting. * You want a year-over-year reference beside it without drawing a whole chart. Use a **table** when several figures matter at once, or a **line chart** when the shape of the development matters more than the latest value. See [Chart Types](/chart-types/). ## Configuration | Setting | Where it is | What it does | | --------------------- | ------------------------------------------ | ------------------------------------------------------------------ | | **Level** | **Level** section of the chart editor | Chooses which level the two values come from. **Year** by default. | | **Sort** | **Sort** dialog, **Level** section | Decides which value is primary and which is secondary. | | **Filters** | **Filters** section | Selects which level values are shown. | | **Comparison** | Chart editor | Adds the delta between the two selected level values. | | **Show labels** | **Formatting** section of the chart editor | Shows or hides the labels beside the values. On by default. | | **Show subtitle** | **Formatting** section | Shows or hides the chart's subtitle. On by default. | | **Scales and Digits** | Button below the **Formatting** section | Sets the scale and the number of decimal places. | A KPI tile has no axes, so these are the only formatting controls it has. A comparison appears in the bottom left corner by default, showing a positive delta in green and a negative one in red. ![The KPI chart settings, with the level and sort options](./images/5310349382.png) ## Good to know * **Exactly two level values, no more.** Selecting a third produces an error saying the chart type does not support more than two values. Delete the comparison or narrow the selection in **Filters**. * **A comparison needs exactly one other value.** With more than one other value selected, the comparison cannot be displayed as a secondary value. * **The large number is the primary value, not the newest one.** If the wrong figure is large, change the order in the **Sort** dialog rather than the filter. ## Related * [Chart Types](/chart-types/): the other chart types and tiles. * [Delta Comparisons](/scenario-time-or-dimension-level-comparison-delta/): how the comparison methods, including CAGR, are calculated. --- # Level Indicators on Nodes URL: https://docs.valsight.ai/level-indicators-on-nodes/ Description: The Visual Level Indicators feature enhances the Model Editor by visually representing where dimensionality changes occur within driver trees. Color-coded le… The **Visual Level Indicators** feature enhances the **Model Editor** by visually representing where dimensionality changes occur within driver trees. Color-coded level indicators in model nodes and operation editors help users instantly identify which levels are involved in each calculation, streamlining model navigation and improving clarity when working with multi-dimensional data. This feature supports transparent modeling practices by embedding dimension-level awareness directly into the visual layout of the Model Editor. ## Key benefits With Visual Level Indicators, users can: * Instantly understand dimensionality at a glance via color-coded level bubbles * Identify where levels are added or dropped within calculations * View and manage level details below the operation editor with informative tags * Customize the display to fit individual preferences or modeling needs ### Example use case A car manufacturer is modeling production planning across various product categories and time levels (e.g., Year, Quarter, Month). Using Visual Level Indicators, the planning team can easily track how time-based dimensions evolve throughout the driver tree, enabling faster validation and clearer communication across stakeholders. ## Setup and usage ### Recommended preparation To ensure optimal use of Visual Level Indicators: * Work with a model that includes **multi-level dimensions** (e.g., time hierarchies or product categories) * Ensure the dimensional structure is well-defined in **Dimension Management** * Keep model complexity manageable to benefit most from the visual enhancements ### Activating visual level indicators Visual Level Indicators are not created manually but are enabled as a **visual overlay** within the Model Editor. To activate: 1. Open a model in the **Model Editor** 2. Open the Inspector on the right and select the **Layout** tab 3. Under **Node Display**, switch on **Show Dimension Levels** Once activated, the following elements will appear: * **Color-coded bubbles** in the bottom-left corner of each node * **Color-coded tags** below the operation editor > **The dimension legend depends on this setting.** **Show Dimension Legend**, one row below in the same section, stays greyed out until **Show Dimension Levels** is on, with the tooltip ‘Activate “Show Dimension Levels” to enable the legend.’ Switch the levels on first and the legend becomes available. ### Interacting with visual level indicators #### Node indicators * Each color bubble represents one **dimension**, not one level. Where a node carries several levels of the same dimension, only the deepest is shown, so a node using Year, Quarter and Month gets a single bubble for Month * The color belongs to the **dimension**, so every level of that dimension shares it and the color is consistent across the model * A number inside the bubble indicates the level's **position in the hierarchy** (e.g., "3" for Month after Year and Quarter) * Bubbles are sorted alphabetically by level name, not by position in the hierarchy #### Truncation * If a node has bubbles for **more than 7 dimensions**, the rest collapse into a **"+X"** bubble * Hovering over the collapsed bubble reveals the full list #### Operation editor tags * Tags are shown **below the operation editor** and are **alphabetically sorted** ## Managing, configuration and limitations ### Supported configuration * Levels are **automatically assigned colors** per dimension * Up to **7 level bubbles** can be displayed per node before truncation * Up to **20 level tags** are shown below the operation editor before truncation * **Tooltips** are available on hover for both tags and truncated bubbles ### Limitations * Long labels are truncated to maintain visual clarity but can be inspected on hover * Excessively large models may impact readability but do not affect functionality ### Data synchronization and integration * Display settings are **saved per model view**, similar to annotations and frames * No additional user rights are required: any user with **edit permissions** can enable or disable the feature * Visual Level Indicators are a **client-side visualization layer** and do not affect the underlying data model ## Summary **Visual Level Indicators** provide a clear and structured way to understand how dimensions are used throughout a model. By combining node-level color bubbles, operation editor tags, and dynamic truncation logic, this feature improves model readability, accelerates validation and debugging, and brings transparency to complex driver trees. --- # LEVELFILTER URL: https://docs.valsight.ai/levelfilter/ Description: Filters the input to rows where a certain condition is met between level values of two compared levels. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **LEVELFILTER** function **filters the input to rows where a certain condition is met between level values of two compared levels**. Use this function when filtering depends on comparing member values between two levels rather than filtering by a fixed value list. ## Syntax `LEVELFILTER('Node', "Level1", "Level2" [, "Operation" [, "CaseSensitive"]])` ## Parameters | Parameter | Description | Type | Required | Default | | ----------------- | --------------------------------------------------------------------------- | -------------- | -------- | -------- | | **Node** | The input node with the values to be filtered. | Node reference | Yes | -- | | **Level1** | The first level whose level values are compared. | Level name | Yes | -- | | **Level2** | The second level whose level values are compared. | Level name | Yes | -- | | **Operation** | The filtering condition. | Keyword | No | `"EQ"` | | **CaseSensitive** | Whether to perform the level value check in a case-sensitive manner or not. | Keyword | No | `"TRUE"` | **Operation options:** * `"EQ"`: Only returns rows where values of `Level1` and `Level2` are equal. This is the default. * `"NEQ"`: Only returns rows where values of `Level1` and `Level2` are different. * `"STARTSWITH"`: Only returns rows where values of `Level1` start with the values of `Level2`. * `"ENDSWITH"`: Only returns rows where values of `Level1` end with the values of `Level2`. * `"CONTAINS"`: Returns rows where values of `Level1` contain the values of `Level2`. **CaseSensitive options:** * `"TRUE"`: Performs the check taking upper/lower case letters into account. This is the default. * `"FALSE"`: Performs the check without taking upper/lower case letters into account. ## Watch out * `Node` must contain both `Level1` and `Level2` to perform the filtering. * `Level1` and `Level2` cannot be the same level. * For the operations `"STARTSWITH"`, `"ENDSWITH"`, and `"CONTAINS"`, the checks are performed based on the first compared level (`Level1`). This means the filtering is made according to whether a level value of `Level1` matches a value of `Level2`, not the other way around. * For the operations `"STARTSWITH"`, `"ENDSWITH"`, and `"CONTAINS"`, equal level values also return true values. ## Examples ### Compare two levels with equality and inequality This example compares two product-related levels and shows how `LEVELFILTER` behaves with equality and inequality checks. The input node contains the levels `Year`, `Product`, and `Other Product`. **Input node:** `'Input node'` | Year | Product | Other Product | Value | | ---- | ------- | ------------- | ----- | | 2025 | Car | Car | 10 | | 2026 | Truck | Plane | 20 | | 2027 | Bicycle | bicycle | 30 | | 2028 | Van | Truck | 40 | **Formula:** `LEVELFILTER('Input node', "Product", "Other Product", "EQ", "FALSE")` | Year | Product | Other Product | LEVELFILTER Result | | ---- | ------- | ------------- | ------------------ | | 2025 | Car | Car | 10 | | 2027 | Bicycle | bicycle | 30 | In this example, only rows with the same level values between `"Product"` and `"Other Product"` are kept. The row with `"bicycle"` is only kept because the operation is not performed case-sensitively. **Formula:** `LEVELFILTER('Input node', "Product", "Other Product", "EQ", "TRUE")` | Year | Product | Other Product | LEVELFILTER Result | | ---- | ------- | ------------- | ------------------ | | 2025 | Car | Car | 10 | This example performs the same equality check case-sensitively, so the row with `Bicycle` and `bicycle` is removed. **Formula:** `LEVELFILTER('Input node', "Product", "Other Product", "NEQ", "FALSE")` | Year | Product | Other Product | LEVELFILTER Result | | ---- | ------- | ------------- | ------------------ | | 2026 | Truck | Plane | 20 | | 2028 | Van | Truck | 40 | The not-equals operation keeps only the rows where the values of `"Product"` and `"Other Product"` differ. **Formula:** `LEVELFILTER('Input node', "Product", "Other Product", "NEQ", "TRUE")` | Year | Product | Other Product | LEVELFILTER Result | | ---- | ------- | ------------- | ------------------ | | 2026 | Truck | Plane | 20 | | 2027 | Bicycle | bicycle | 30 | | 2028 | Van | Truck | 40 | With case-sensitive comparison enabled, `Bicycle` and `bicycle` are treated as different values and are therefore kept. ### Use string comparison operations This example shows how `STARTSWITH`, `ENDSWITH`, and `CONTAINS` work when comparing text-like level values. **Input node:** `'Input node'` | Year | Filter Year | Value | | ---- | ----------- | ----- | | 2025 | 20 | 10 | | 2026 | 202 | 20 | | 2027 | 02 | 30 | | 2024 | 24 | 40 | **Formula:** `LEVELFILTER('Input node', "Year", "Filter Year", "STARTSWITH")` | Year | Filter Year | LEVELFILTER Result | | ---- | ----------- | ------------------ | | 2025 | 20 | 10 | | 2026 | 202 | 20 | In this example, only the rows where the values of `"Year"` start with the values of `"Filter Year"` are kept. (`20`25, `202`6) **Formula:** `LEVELFILTER('Input node', "Year", "Filter Year", "ENDSWITH")` | Year | Filter Year | LEVELFILTER Result | | ---- | ----------- | ------------------ | | 2024 | 24 | 40 | In this example, only the rows where the values of `"Year"` end with the values of `"Filter Year"` are kept. (20`24`) **Formula:** `LEVELFILTER('Input node', "Year", "Filter Year", "CONTAINS")` | Year | Filter Year | LEVELFILTER Result | | ---- | ----------- | ------------------ | | 2025 | 20 | 10 | | 2026 | 202 | 20 | | 2027 | 02 | 30 | | 2024 | 24 | 40 | In this example, all rows are kept since each `Year` value contains the value in `Filter Year`. (`20`25, `202`6, 2`02`7, 20`24`) ## Related | Function | When to use instead | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | | [FILTER](/filter/) | When you want to filter by explicit level values or simple conditions on one level instead of comparing values between two levels. | | [EQ (=)](/eq/) | When you want a 1/0 comparison flag between two inputs instead of directly filtering rows out of the result. | --- # Licenses, User Types & Access Management URL: https://docs.valsight.ai/licenses-user-types-access-management/ Description: Valsight is licensed based on the number of named users. A named user is any natural person authorized by the customer to use the software under the terms st… Valsight is licensed based on the number of named users. A named user is any natural person authorized by the customer to use the software under the terms stated in the overarching Valsight Agreements. The maximum number of users is defined by the license. The licensed users are differentiated by *user types,* whereas each type allows users to use different parts of the application. The current usage and capacity can be viewed on the license page by system admins. Supported user types: 1. **Analyst/Basic User**: Can access simulation workspaces and build charts, but not change any data (no Scenario Manager access). Can view and create presentations. 2. **Simulation User:** Same as the Analyst/Basic User + can access simulation workspaces, change data in the Scenario Manager, can upload/update/edit data sources and use Workflows. 3. **Model User:** Same as Simulation User + can create and edit projects, models, dimensions, and data sources and use and edit Workflows. 4. **Unrestricted User:** Same as Model User + can be a global admin which lifts all restrictions and enables full access, e.g. to settings and configuration. **Note:** User types only impose restrictions on top of access rights, users still need to be given specific rights for each project/model/workspace/presentation/workflow that they want to access. Additionally, this also means that users with a restricted user type (e.g. being a basic user) will not be able to open a project although they have been given access to it. ## Valsight access management While there are 4 types of licenses, Valsight offers additional options on how to further define access rights for advanced customization among users.

Places to edit the Valsight Access Management

Licenses

The initial access rights for each user are defined by the license type. Being able to choose between 4 different types of users, enables individually composed license packages.

Valsight settings

Access rights

The access rights settings can be reached via the Valsight settings. Here, permissions can be granted in an overview of projects, Models, Workspaces and presentations. Learn more.

User management

The user management can be reached via the Valsight settings. Here, you can edit the permissions of each individual user. Learn more.

Group management

The group management can be reached via the Valsight settings. Here, access rights can be provided by assigning users to groups. Learn more.

Data permission classes

The data permission classes can be reached via the Valsight settings under 'Projects > Security'. Data permissions define which data a user can access. They can be configured for a project and will be enforced for Charts in Simulation Workspaces. Learn more.

## Overview of user type access limitations > * The premise for users to have the access rights mentioned in the table below is that the according access rights have been granted. > > * The table shows the maximum possible access for a specific license type. To reach that maximum, proper access rights have to be given. > * The unrestricted user has the same abilities as a Model User except for the ability to be a global admin. > > The access to projects, models and workspaces can further be split into 2 levels each. This enables the split between users actively working in a space and users viewing the space for information purposes. > > * By creating a new project (as any eligible user type) you automatically become the project admin for the respective project.

Project

Model

Workspace

Can Use

(Project/Global) Admin

Read-Only/Can View

Can Edit

(Project/Global) Admin

Limited Access

Full Access

(Project/Global) Admin

> In the table below, we only focused on those limitations that have a direct influence on the user type.

Analyst/Basic User

Simulation User

Model User

Unrestricted User

Project

(Creating a project automatically makes you that project’s admin)

Can Use

Can Use

Can Use

Project Admin

Global Admin

  • Cannot create a project

  • Cannot delete

  • Cannot duplicate

  • Cannot upload image

  • Can open and see the project settings, but cannot change or edit anything

    • Not able to import scenarios

    • Not able to configure variables

  • Cannot change access rights

Info:

No change in rights if selected as project admin (In the access control, it's shown as “Can Use” although I have set it to project admin)

  • Cannot create project

  • Cannot delete

  • Cannot duplicate

  • Cannot upload image

  • Can open and see the project settings, but cannot change or edit anything

    • Not able to import scenarios

    • Not able to configure variables

  • Cannot change access rights

  • Project admin rights (only effect on data sources)

    • Can see/ create/delete/edit data sources

  • Can create project

  • Cannot delete (except your own)

  • Cannot duplicate (except your own)

  • Cannot upload image (except your own)

  • Can open and see the project settings, but cannot change or edit anything (except your own)

    • Not able to import scenarios

    • Not able to configure variables

  • Cannot change access rights

  • Can create projects

  • Can delete projects

  • Can duplicate

  • Can upload images

  • Can open, see and edit project settings

    • Can Import scenarios

    • Can configure variables

  • Can change access rights

Info:

A Modeler that is project admin, can only have “Can Edit” rights on a model!

Info:

A Modeler that is project admin, can only have “Full Access” on a workspace!

  • Full access to projects

    • Can edit project settings

    • Can access and edit the project

    • Can create/delete users and groups

Model

Creating a model automatically gives you “Can Edit” rights for that model

Read-Only/Can View

Read-Only/Can View

Read-Only/Can View with Can Use rights for project

Info:

Read-Only/Can View not possible when Modeler is project admin.

Can Edit with Can Use rights for the project

Can Edit with Project Admin rights for the project

Info:

A Modeler that is project admin, can only have “Can Edit” rights on a model.

Global Admin

  • Model overview

    • Cannot create model

    • Cannot delete model

    • Cannot upload image

    • Cannot duplicate model

    • Can see model graph - but only names of models with access

    • Cannot open/see model settings dialog

  • In the model

    • Cannot upload data/create data source

    • Can download model specific data sources

    • Cannot edit nodes (settings, formulas) but can see all formulas and all settings

    • Cannot create/delete nodes

    • Cannot move nodes

    • Cannot create Sections

    • Can see Data Preview

    • Can change validation settings

  • Model overview

    • Cannot create model

    • Cannot delete model

    • Cannot upload image

    • Cannot duplicate model

    • Can see model graph - but only names of models with access to

    • Cannot open/see model settings dialog

  • In the model

    • Cannot upload data/create data source

    • Can download model specific data sources

    • Cannot edit nodes (settings, formulas) but can see all formulas and all settings

    • Cannot create/delete nodes

    • Cannot move nodes

    • Cannot create sections

    • Can see data preview

    • Can change validation settings

Info:

Can be selected to have “Can edit” rights, but does nothing

  • (In the access control, it's shown as “Can Use” although I have set it to project admin)

  • Model overview

    • Cannot create model (except your own)

    • Cannot delete model (except your own)

    • Cannot upload image (except your own)

    • Cannot duplicate model

    • Can see model graph - but only names of models with access

    • Cannot open/see model settings dialog

  • In the model

    • Cannot upload data/create data source

    • Can download model specific data sources

    • Cannot edit nodes (settings, formulas) but can see all formulas and all settings

    • Cannot create/delete nodes

    • Cannot move nodes

    • Can copy nodes

    • Cannot paste nodes

    • Cannot create Sections

    • Can see Data Preview

    • Can change validation settings

  • Model overview

    • Cannot create

    • Can delete

    • Cannot duplicate

    • Can upload image

    • Can see model graph - but only names of models with access

    • Can see and edit model settings

  • In the model

    • Cannot upload/create model data source

    • Can download model specific data sources

    • Can see and edit nodes (settings & formulas)

    • Can create/delete nodes

    • Can move nodes

    • Can copy nodes

    • Can paste nodes

    • Can create sections

    • Can see data preview

    • Can change validations

  • Model overview

    • Can create

    • Can delete

    • Can duplicate

    • Can upload image

    • Can see model graph

    • Can see and edit model settings

  • In the model

    • Can upload data/create data source

    • Can download model data

    • Can see and edit nodes (settings & formulas)

    • Can create/delete nodes

    • Can move nodes

    • Can copy nodes

    • Can paste nodes

    • Can create sections

    • Can see data preview

    • Can change validations

  • Full access to models

    • Can see the models

    • Can access and edit models

    • Can create models

Workspace

Creating a workspace automatically gives you Full Access on that workspace

Limited Access

Info:

Cannot have Full Access.

Limited Access

Full Access

Limited Access and Can Use on project

Info:

Limited Access not possible when the user is project admin.

Full Access and Can Use on project

Info:

If you create a workspace (even with Limited Access) you have full access automatically.

Project Admin

Info:

A modeler that is project admin, can only have “Full Access” on a workspace.

Global Admin

  • Workspace overview

    • Cannot create workspace

    • Cannot delete workspace

    • Cannot open/see workspace settings dialog

    • Cannot upload ws picture

    • Cannot duplicate

    • Possible to see shared scenarios

    • Not possible to unshare scenarios

  • In the workspace

    • Can change validation settings

    • Able to add/delete and edit workspace filters

    • Full interaction with worksheets

    • Can see Scenario Manager but not edit/share/duplicate anything in there

      • You can save a version, restore an old version but cannot delete and old version (in the new world)

    • Can add/remove columns

    • Can collapse/decollapse assumption groups

    • Able to use search function / custom property filters

  • Workspace overview

    • Can create workspaces

    • Can delete

    • Can duplicate

    • Can upload image

    • Cannot open/see workspace settings dialog

    • Can see shared scenarios

    • Cannot unshare shared scenarios

  • In the workspace

    • Can change and trigger validation settings

    • Able to add/delete and edit workspace filters

    • Full interaction with worksheets

    • Can see Scenario Manager but not edit anything in there

    • Can add/remove columns

    • Can collapse/decollapse assumption groups

    • Able to use search function / custom property filters

  • Can change access rights for the workspace

  • Workspace overview

    • Can create workspaces

    • Can delete

    • Can duplicate

    • Can upload image

    • Can edit the workspace settings

    • Can see shared scenarios

    • Cannot unshare shared scenarios (except scenarios shared by themselves)

  • In the workspace

    • Full interaction with worksheets possible

    • Full interaction with Scenario Manager possible

  • Workspace overview

    • Can create workspaces

    • Cannot delete (except own ws)

    • Cannot duplicate (except own ws)

    • Cannot upload images (except own ws)

    • Cannot see settings

    • Can see shared scenarios

    • Cannot unshare shared scenarios (except scenarios shared by themselves)

  • In the workspace

    • Able to trigger validation and change validation settings

    • Able to add/delete and edit workspace filters

    • Full interaction with worksheets

    • Can see Scenario Manager but not edit anything in there

  • Can change access rights for the workspace

  • Workspace overview

    • Can create workspaces

    • Can delete

    • Can duplicate

    • Can upload image

    • Can edit the workspace settings

    • Can see shared scenarios

    • Can unshare shared scenarios

  • In the workspace

    • Full interaction with worksheets possible

    • Full interaction with Scenario Manager possible

  • Can change access rights for the workspace

  • Workspace overview

    • Can create workspaces

    • Can delete

    • Can duplicate

    • Can upload image

    • Can edit the workspace settings

    • Can see shared scenarios

    • Can unshare shared scenarios

  • In the workspace

    • Full interaction with worksheets possible

    • Full interaction with Scenario Manager possible

  • Full access to Workspaces

    • Can edit/change workspaces

    • Can interact with the Scenario Manager

    • Can change access rights for workspaces

Data Source

Can Use/No Access on project level

Can Use/No Access on project level

Project Admin on project level

Can Use on project level

Project Admin

Global Admin

  • No access to data sources

  • No access to data sources

  • Can see data sources

  • Can update/edit data sources

  • No access to data sources

  • Can see data sources

  • Can change/delete/edit/upload data sources

  • Full access to data sources

    • Can see data sources

    • Can edit data sources

Export Manager

  • Create exports

  • View and manage own exports

  • Can update own exports

  • Create exports

  • View and manage own exports

  • Can update own exports

  • Create exports

  • View and manage all exports

  • Can update all exports

  • Create exports

  • View and manage own exports

  • Can update own exports

  • Create exports

  • View and manage all exports

  • Can update all exports

  • Create exports

  • View and manage all exports

  • Can update all exports

Data Permission Class

Can Use/No Access on project level

Can Use/No Access on project level

Project Admin on project level

Can Use on project level

Project Admin

Global Admin

  • Can view data permission classes

  • Cannot edit data permission classes

  • Cannot decide who gets read or write access

Info:

Any user can be granted read or write access to the data covered by a permission class. Read = view all line items and their results, without simulating line-item values. Write = view and simulate line-item values.

  • Can view data permission classes

  • Cannot edit data permission classes

  • Cannot decide who gets read or write access

  • Can view and edit data permission classes

  • Can decide who gets read or write access

  • Can view data permission classes

  • Cannot edit data permission classes

  • Cannot decide who gets read or write access

  • Can view and edit data permission classes

  • Can decide who gets read or write access

  • Full access to data permission classes

    • Can view and edit data permission classes

    • Can decide who gets read or write access

Dimension

  • No access to Dimensions

  • No access to Dimensions

  • No access to Dimensions

Project Admin

Global Admin

  • Can see the Dimensions

  • Can change/delete/edit Dimensions

  • Full access to Dimensions

Can Use on project level

Project Admin

Workflow

  • Cannot create a workflow

  • Cannot configure workflow steps

  • Cannot create workflow steps

  • Can update submission data, promote and demote steps via the workflow menu and via the Scenario Manager (when permission rights are assigned)

  • Cannot create a workflow

  • Cannot create workflow steps

  • Cannot configure workflow steps

  • Can update submission data, promote and demote steps via the workflow menu and via the Scenario Manager (when permission rights are assigned)

  • Cannot create a workflow

  • Cannot create workflow steps

  • Cannot configure workflow steps

  • Can update submission data, promote and demote steps via the workflow menu and via the Scenario Manager (when permission rights are assigned)

  • Can create

  • Can edit

  • Can configure workflow steps

  • Can create workflow steps

  • Can update submission data, promote and demote steps via the workflow menu and via the Scenario Manager

  • Full access to Workflows

    • Can create/edit Workflows

    • Can create Workflow steps

    • Can configure Workflow steps

    • Can promote/demote Workflow steps

Presentations

  • Can create presentations

  • Can view presentations

  • Can delete presentations

  • Can create presentations

  • Can view presentations

  • Can delete presentations

  • Can view presentations

  • Can create presentations

Global Admin

  • Full access to presentations

    • Can view/create presentations

    • Can change access rights to presentations

Can be Global Admin

No

No

No

Yes

### Advanced configuration User types are chosen when creating an account and can also be changed later. Disabled users do not count towards the limit. If you have reached the capacity for a certain type and create a new user, that user will be created as disabled. Enabling a user is allowed as long as you don't exceed the capacity of that user's type. When logging in via SSO and auto-creating users, the default type of a new account is *unrestricted* but can be changed by modifying the 'autoCreatedUserType' option from the config.yml (see [Common SSO Options](#)). --- # Limitations & Data Sizing Guidelines URL: https://docs.valsight.ai/limitations-data-sizing-guidelines/ Description: Valsight allows you to build complex models and the performance of the system is dependent on the actual model and especially the amount of data that is crea… Valsight allows you to build complex models and the performance of the system is dependent on the actual model and especially the amount of data that is created during multi-dimensional calculations. This page tries to give an overview of tested configurations. | Topic | Supported | Enforced | Notes / Recommendation | | -------------------------------------------------------- | ---------------------------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Max Excel File upload size | < 20 MB | 20 MB | Typical Valsight models use aggregated data which fits in \~1 MB files. | | Max number of rows per Sheet in XLS file | 100000 | Excel Maximum = 1048576 rows | Structure your data to not use more than 100.000 rows. Parsing Excel files needs plenty of memory. If working with larger workbooks is mandatory, make sure to run on at least 16 GB. Some frontend parts such as the "Table View" component perform poorly in the browser. Use the server-side table viewer from the admin config interface instead. | | Maximum number of columns per sheet | 26 | Excel Maximum | There is no enforced limit, but the frontend is tested to work with this amount. Note that Excel parsing is dependent on the number of rows and columns. The largest supported configuration contains 100.000 x 26 = 2.6M data cells. | | Level Member | 20000 | not enforced | There is no enforced limit, but the frontend is tested to work with this amount. | | Max number of Dimensions / Hierarchies | 10 | not enforced | There is no enforced limit, but the frontend is tested to work with this amount. | | Number of data rows per Cube | 100000 | not enforced | A cube is the result of a calculation or the underlying data table for a data node. The upper bound of possible values can be calculated as the cross product of all level members, however most real-world examples have very sparse cubes. There is no enforced limit. | | Number of rows per OData/JDBC data source | Dependent on server hardware | not enforced | The default value is set to 100.000. It can be changed in the Valsight settings > Settings under 'System' and the feature flag 'featureFlags.limitODataAndJDBCRowsUpTo'. | | Maximum number of levels per Hierarchy (Hierarchy Depth) | 7 | not enforced | There is no enforced limit, but the frontend is tested to work with this amount. | | Maximum number of data rows per Assumption Line-Item | 1000 | enforced, but configurable | This limit is configurable in the admin section. Higher values may reduce the performance of the frontend. Extending the possible number of rows that can be entered via assumptions is a current focus topic of the Valsight R\&D team. | | Number of concurrent users | | Highly dependent on the model & user behavior, and CPU and RAM of the server. | You can estimate the amount of concurrent users by estimating the runtime of an average simulation run and the amount of simulations necessary to sustain a certain user behaviour. Models, where the simulation takes two seconds, can therefore roughly sustain 0.5 simulation per CPU core. For example, assuming a user performs a simulation every 10 seconds, an entry level 4 core system can provide enough performance for 0.5*4*10 = 20 **concurrent** users. Please note that only changes to an assumption count as simulation. | | Number of Models | 100 | not enforced | The amount of present models has no negative performance impact. | | Number of Workspaces | 200 | not enforced | The amount of simulation workspaces has no negative performance impact. | | Number of Assumptions (Groups) per Workspace | 30 | not enforced | There is no enforced limit, but the frontend is tested to work with this amount. | | Number of Assumption Line-Items per Workspace | 120 | not enforced | There is no enforced limit, but the frontend is tested to work with this amount. | | Number of Template Charts per Model | 20 | not enforced | There is no enforced limit, but the frontend is tested to work with this amount. | | Sequence Dimension | 0-99999 | enforced | | --- # Line-Item Data & Details URL: https://docs.valsight.ai/line-item-data-details/ Description: To see the data of a Line-Item, click on the name the Line-Item. To see the data of a Line-Item, click on the name the Line-Item. The data view will open on the right side of the screen. In the columns of the data table are the levels of your Line-Item, the ‘Base’ that comes from the model, the ‘Change’ column, the ‘Result’ column, and a column where you can enter a comment or description for each row. Setting filters for the columns on that screen can be used to temporarily focus the view onto the data. After the next browser refresh or after leaving the data view, these filters have been reset. > **Saving a data entry while rows are filtered out overwrites the hidden rows.** Whenever a workspace or line-item filter hides part of the table, Valsight says so above it: ‘Since a workspace or line-item filter is active, {n} rows are not displayed. Saving a data entry in the filtered view overwrites all adjustments of the hidden rows.’ Note that a **workspace** filter triggers this too, not only the line-item's own filters. > **A very large line-item variant will not be displayed at all.** There is a row ceiling on this table, set per instance. Above it the table refuses to render and reports ‘The size of the line-item variant (… rows) is larger than the allowed number (… rows) set in the instance settings (maxLineItemDisplay).’ Use the Excel download and upload to work with the data instead, or ask an administrator to raise the limit. ![image-20241106-092923.png](./images/6701318156.png) To see the details of your Line-Item, click on the “Details” button in the upper right corner. On that screen, you can see more details of your Line-Item. ![image-20231026-092355.png](./images/6701318163.png) ## Supported number formats in Line-Item tables Valsight Line-Item tables support numeric values only, with flexible formatting options to streamline data entry. Below is a guide to the supported formats and behaviors: ### Supported formats * **Numbers**: Standard numeric values such as `1`, `1.21`, or `1,21` are supported. * **Decimal Separator**: The use of `comma` or `dot` for decimal places depends on your language settings. * **Percentages**: You can paste percentages directly. For example, entering `12` will be interpreted as `12%`. ### Flexible input handling * **Copy & Paste**: Values can be copied from sources like Excel, and non-numeric characters (e.g., `€`, `$`, or `a`) will automatically be removed. For example: * Pasting `12€` becomes `12`. * Pasting `12a` becomes `12`. * **Units and Symbols**: Letters or symbols at the end of a number are removed. ### Unsupported formats * **Non-Numeric Strings**: Entries like `12ab1` or `abc` are not supported. * **Multiple Decimals**: Values such as `12.1.2` are invalid When pasting multiple values or cells into a Line-Item table, any valid numbers will be processed and inserted, while invalid entries will be ignored. A toast message will appear to inform you of the skipped values, listing all invalid entries for your reference. ## Pivoting the line item data table Pivoting the Line Item Data Table enhances data visualization and entry by allowing the time dimension to be displayed in columns rather than in rows. This is particularly beneficial for faster adjusting data or copying and pasting data from spreadsheets. To access this feature, select “Change View” or “Results View” from the “All Details” dropdown within a line item view. * "Change View" simplifies entering expected changes (e.g., a 2% sales volume increase in 2025). * "Results View" allows inputting desired outcomes (e.g., desired result of 4% increase in sales volume in 2025). ![image-20240408-141013.png](./images/6701318169.png) Adjusting data in one view dynamically updates the other, enabling comprehensive analysis and easier data management. ## Manage levels To change the dimensionality of your relative Line-Item, use the “Manage levels” button in the details view. This dialog shows the levels of the dimensionality of your Line-Item. For relative Line-Items it is possible to delete or add levels. ![image-20231002-121844.png](./images/6701318175.png) ## Match node In case your Line-Item does not match the dimensionality of the underlying node, a warning in the data view and an extra button will be displayed. Using this button (“Match Node”) will automatically bring the Line-Item onto the dimensionality of your node and the warning will no longer be shown. ![image-20231002-122532.png](./images/6701318181.png) --- # Line-Item Filters URL: https://docs.valsight.ai/line-item-filters/ Description: Permanently filters a Line-Item to the selected criteria. Has an effect on following calculations. Is saved an effects all users. When sharing a scenario, on…

Filter Name

Type

Persisted

Synchronised

After Sharing

Across Users

Line-Item Filter

Saved project-wide

For entire workspace and all Line-Item views.

Edit View Filter

Saved project-wide

For entire workspace in change and results view.

Table View Filter

Not saved

Across change and results view.

> **Saving a data entry while rows are filtered out overwrites the hidden rows.** Whenever a workspace or line-item filter hides part of the table, Valsight says so above it: ‘Since a workspace or line-item filter is active, {n} rows are not displayed. Saving a data entry in the filtered view overwrites all adjustments of the hidden rows.’ Note that a **workspace** filter triggers this too, not only the line-item's own filters. ## 1. Line-Item filter (details) > Permanently filters a Line-Item to the selected criteria. Has an effect on following calculations. Is saved an effects all users. When sharing a scenario, only the values which match the filter criteria are included. ![image-20231002-122806.png](./images/6702661647.png) The “Manage Filters” dialog relates to [filters](/filters-in-valsight/) set on the levels that affect the view onto the data of a line-item. The filters set here are permanent and effect all calculations by this Line-Item. To set a filter on one of the levels in the line-item, click on the level first and then adjust the filters to your desired view. To set filters on a level, it must be in the dimensionality first. ## 2. Line-Item change view filter (edit) > Permanently filters a Line-Items table. Is persisted and shared across users. Does not have an effect on calculations. Has no effect when sharing a scenario. ![image-20240529-160452.png](./images/6702661654.png) To create a table view that is filtered and displayed in a user-defined manner, select the View dropdown and change it from 'All Details' to 'Change View'. This is a custom view that can be flexibly defined and changed. It is persisted and saved for all users. This is ideal for preparing an input table for a simple view, but does not affect any calculations or completely exclude any values from this item. Now click on ‘Edit' to edit the view. Select 'Filter' and choose the criteria by which you wish to filter the table. Click on 'Save’ to persist this view for every user in this workspace. ![image-20240529-160533.png](./images/6702661660.png) ## 3. Table view filters (column) > Filters the table view for you personally. Has no effect on calculations or other users. Is not persisted or saved in any way. It is, however, synchronized across the change and results view. Has no effect when sharing a scenario. ![image-20240528-143459.png](./images/6702661666.png) This filter is best used if you wish to temporarily filter a Line-Item table for an easier data input or analysis. It is neither persisted nor shared with other users. You can filter the Line-Item table using the column filters. You can either filter by available values or by a user-defined condition. Filters are synchronized across views, so the rows remain filtered according to your settings even when switching between results, change and standard. ![image-20240528-143225.png](./images/6702661672.png) > Line-Item Filters are synchronized across change and results view. ## Copy and paste support for percentages and thousand separators Copying and pasting values from external sources like Excel into Valsight is supported with the following behaviour and helpers: * **Flexible Input Parsing:** Users can now paste percentages, numbers with thousand separators, or values with symbols (e.g., %, €, $) without encountering errors. These characters are automatically ignored at the beginning or end of the input. * **Language-Aware Thousand Separators:** Thousand separators (e.g., `,` for English or `.` for German) are now supported and correctly interpreted based on the **Valsight language settings**. * **Invalid Input Handling:** If invalid values are detected (e.g., `123test456`), an error message will notify users with a detailed explanation and a link to the **documentation** for correct formatting guidance. --- # Line-Item Variants URL: https://docs.valsight.ai/line-item-variants/ Description: Line-Item variants can be understood as different variations of a single Line-Item and are implemented in the Scenario Manager. Line-Item variants can be understood as different variations of a single Line-Item and are implemented in the Scenario Manager. They allow you to simulate scenarios based on the same Line-Item but with each Line-Item variant having modifications in data. The feature of Line-Item variants improves the clarity of the Scenario Manager and improves the usability of scenario simulations as it helps to group Line-Items. > **Maximum Variants per Line Item** > > The amount of variants per Line-Item is configurable in the Valsight settings > Settings under 'System' and 'featureFlags.maxVariantsLimitForLineItems'. > > The default value is 20 variants per Line-Item. ## Using Line-Item variants Line-Item variants are used in the Scenario Manager and can be created, edited, and deleted via the Line-Item settings. To create a Line-Item variant: 1. Open the Line-Item a variant should be created for 2. Click on the plus on the right side of the window 3. Name your Line-Item variant 4. Deleting a Line-Item variant can be done via the drop-down next to the variants name ![Variants.gif](./images/5094207214.gif) To change the Line-Item variant or deactivate the Line-Item for a scenario, navigate to the Line-Item drop-down menu. Select either another Line-Item variant or 'Inactive' in case you want to deactivate the Line-Item. ![image2021-8-6\_16-57-30.png](./images/5094204563.png) > **Deleting variants** > > When a variant is activated in the Scenario Manager but gets deleted, the Line-Item will be deactivated for that scenario. ## Duplicating & renaming Line-Item variants Navigate to the variant's three-dot menu to find the duplicate button. You can then rename the variant directly. ![image-20240716-145128.png](./images/5621743623.png) Double-click a variant's name to rename it afterward. ### Reordering variants **Reorder Variants**, opened from the variant tab bar, lets you drag the variants into the order you want. The order you set is the order of the tabs. The action is disabled while a line-item has only one variant. ## Line-Item variants in the workspace **Example** A variant can be used to simulate a scenario based on the same Line-Item but with for example slightly adjusted data. ![image2022-2-17\_16-32-8.png](./images/5094231156.png) ## Line-Item configurations Filters work on a Line-Item level. If you set a filter on a Line-Item, it applies to all variants of this Line-Item. Reconfigurations (e.g. filters, nodes) impact all Line-Item variants. When duplicating, sharing, or versioning a Line-Item, all variants are included. More information regarding the versioning of assumptions and Line-Items with variants can be found under [Assumption Versioning](/assumption-versioning/). Using sliders for Line-Items with more than one Line-Item variant is not possible. See [Sliders](/sliders/) to learn more. > **Restrictions** > > * The **Effect** column cannot be used when a Line-Item has more than one Line-Item variant. > * The activation checkbox of the whole **assumption** is disabled in every scenario column as soon as any one of its Line-Items has multiple variants, with the tooltip ‘Multiselect is disabled for assumptions that contain line-items with multiple variants’. Each Line-Item then has to be switched on or off individually through its own variant dropdown, so a second variant costs you one-click activation of that assumption. --- # Line-items URL: https://docs.valsight.ai/line-items/ Description: Line-items are the smallest unit of change in a simulation. Each line-item defines how the value of a single node is adjusted within an assumption. Line-items are the smallest unit of change in a simulation. Each line-item defines how the value of a single node is adjusted within an assumption. ## Why it is relevant * Makes changes to model drivers explicit and controllable * Supports granular, targeted simulations * Keeps alternative assumptions comparable and transparent ## How it works A line-item represents **one concrete change to one node**. Each line-item: * Is always assigned to exactly one assumption * Affects exactly one simulation-enabled node * Describes how that node’s values change (absolute or relative) * Can be filtered to apply only to specific parts of the data By combining multiple line-items within an assumption, complex simulations can be built from small, explicit changes. ![Line-items.png](./images/6664519692.png) Line-items can also have **variants**, allowing alternative versions of the same change (for example optimistic vs. pessimistic). ## Using the feature * Use line-items to express precise changes to individual drivers. * Combine multiple line-items to represent a broader assumption. * Use variants to model mutually exclusive alternatives. * Open a line-item to type or paste values into its data table. [Line-Item Data & Details](/line-item-data-details/) covers that table and the [number formats it accepts](/line-item-data-details/#supported-number-formats-in-line-item-tables), which is where to look if an entry is rejected. ## Characteristics * Line-items can only change simulation-enabled nodes. * Line-items do not exist on their own; they always belong to an assumption. * A line-item is locked while someone edits it, so a second person opens it read-only. See [Parallel access](/parallel-access/). ## Access & permissions Line-items follow the same permissions as assumptions and scenarios. Opening the Scenario Manager only needs view access. Creating and modifying line-items needs **Full Access** on the workspace *and* at least a Simulator user type. See [Licenses, User Types & Access Management](/licenses-user-types-access-management/). ## FAQ **What is the difference between an assumption and a line-item?** An assumption groups changes conceptually, while line-items define the individual changes. **Can a line-item affect multiple nodes?** No. Each line-item applies to exactly one node. **Can line-items be reused?** Yes. Line-items can be duplicated and adapted. **Are line-items optional?** No. Every assumption is built from one or more line-items. ## Related * [Assumptions](/assumptions/) * [Line-Item Data & Details](/line-item-data-details/): the data table, and the number formats it accepts * [Line-Item Variants](/line-item-variants/) --- # Linked levels URL: https://docs.valsight.ai/linked-levels/ Description: Levels in your dimension can be extended with information by adding labels. Levels in your dimension can be extended with information by adding labels. These labels are levels with extended information that are linked to the existing levels. With this, the extended information is added to all the data in your project and can be visualized in the workspace. ## Step-by-step approach Valsight allows you to add/remove labels to desired levels of a dimension. These labels can be called 'linked levels'. In the following, linked levels or linked attributes will be referred to as "labels". Given the case that you have a hierarchy/dimension (e.g. '*Products'*) with several levels, e.g.

Dimension: Products

Levels

Product Family

Product Line

Level Values

A

A12

A13

B

B12

B13

If you realize during your process that you want to add other information, e.g. to a '*Productline*' value, you can add this as a label to the level. The first step is to create a new dimension, containing the missing information. ![image2018-12-18\_13-44-34.png](./images/5094192297.png) You can link the missing information to a certain level (e.g. '*Productfamily'*) by linking it as a level. Therefore choose 'Configure Hierarchie' in the dimension tab. ![image2018-12-18\_13-45-20.png](./images/5094192292.png) Let's say you want to expand the '*Productfamily'* by the information of packaging, e.g. Product A to cardboard. ![image2018-12-18\_14-45-49.png](./images/5094192272.png)![image2018-12-18\_14-48-27.png](./images/5094190719.png) Now the level '*Productfamily*' is linked to the desired label (to Packaging). But in our case both level values A and B are now linked to the label cardboard, because it's always referenced first. ![image2018-12-18\_14-54-31.png](./images/5094190714.png) This means: to expand a certain level value by a certain information, you need to have the same input information available for all other level values. To add the remaining information choose 'Download Excel' and for our example the following excel appears. ![image2018-12-18\_15-2-33.png](./images/5094190724.png) Now you type in the matching information for the other level values. ![image2018-12-18\_15-3-20.png](./images/5094192230.png) Afterwards you do 'Upload Excel' and import the changed excel sheet. ![image2018-12-18\_15-7-44.png](./images/5094192235.png) Now you extended a level of a dimension successfully. Your additional information is added to all the data in your project containing this level. ## Performance improvements ### Overview When running calculations with labels included, it might cause performance issues on the user side. To avoid these issues, users can **exclude labels from calculations**. Your numbers do not change. A label is derived from the level it is attached to, so it never holds information the level itself does not already carry, and line-item data is stored against the underlying level either way. What you gain is speed. > **This is not a display setting, so change it deliberately.** Excluding or including a label rewrites every line-item on that level and on the finer levels of the same dimension, following any chained labels, and clears the project's calculated results so they are worked out again. Expect the project to recalculate afterwards, and avoid toggling it during a presentation. ### Step-by-step approach To include or exclude labels from the calculations: 1. Go to ['Configure Hierarchy'](/creating-maintaining-dimensions/) in the initial dimension. 2. Use the three-dot menu of the respective level. 3. Click on 'Edit Attributes'. 4. Use the switch button to either include or exclude labels in the calculation. Per default, labels are not included in calculations. Labels used in calculations are also marked with a '(calculations)' in the 'label' column. ![image2022-11-23\_13-30-3.png](./images/5094230381.png) --- # LN URL: https://docs.valsight.ai/ln/ Description: Returns the natural logarithm of a number (logarithm with base e ~2.718), while retaining all dimensions. Use when you need a natural logarithm transformation for positive numeric values. **Category:** [Math & numeric](/math-numeric/) ## Overview The **LN** function **returns the natural logarithm of a number** (logarithm with base e \~2.718), while retaining all dimensions. Use this function when you need a natural logarithm transformation for positive numeric values. ## Syntax `LN('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | ---------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | ## Examples ### Natural logarithm of integer and decimal values This example shows the natural logarithm computed for a node with integer and decimal values. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 3 | | 2027 | 4.5 | **Formula:** `LN('A')` | Year | LN Result | | ---- | --------- | | 2025 | 0.69 | | 2026 | 1.10 | | 2027 | 1.50 | ## Related | Function | When to use instead | | ------------ | -------------------------------------------------------------------------------- | | [LOG](/log/) | When you need a logarithm with a specific base instead of the natural logarithm. | | [EXP](/exp/) | When you need exponentiation with base e, or the inverse operation of `LN`. | --- # Locking and Unlocking of Projects URL: https://docs.valsight.ai/locking-and-unlocking-of-projects/ Description: - A project can be locked to finalize modeling in the creation process A project can be locked to finalize modeling in the creation process. Locking prevents any further changes from models, so a locked project can only be changed from workspaces, ensuring an immutable base for calculations. ## Locking a project Locking a project is a useful measure for when the base data and model of a project have been finalized and you want to make sure that no accidental changes can be applied to it. By locking a project, you can ensure that your associates cannot change a project’s basis. Lock a project by clicking the corresponding button in the admin UI under the projects' settings. ![Lock Doku.png](./images/5094194263.png) Locking and unlocking need **Can edit** or **Admin** rights on the project *and* a Modeler user type or above. A project admin qualifies, but so does any Modeler with edit rights, so this is not an admin-only action. A Basic or Simulator user cannot lock a project whatever their project rights. ## Effects of locking a project When a project is locked, most changes to it are prevented until the project is unlocked. More specifically, models, dimensions, and data sources can no longer be changed in any way. This includes adding or deleting instances; doing so is not possible while a project is locked. The only possible changes to a locked project can occur from a workspace. Creating and editing line-items, assumptions and scenarios is still possible when a project has been locked. ## Limitations and best practices ### Project locking and scenario sharing Users will be informed that a project is not locked when creating scenario assumptions. This is to prevent confusion; while the assumptions of shared scenarios cannot be changed, the underlying model to which they are applied could be unlocked and thus edited. This could lead to some sudden changes in the calculation results that might be hard to comprehend at first. ![Screen Shot 2018-03-05 at 10.52.30.png](./images/5094191503.png) ### Working on a project when it gets locked If a project gets locked, there will be no notification about the locking to any of the users working on it. The locking will however appear in the project’s log data. In some situations, a user might still be working on a project at the time it is getting locked; if this should occur, the user will soon start to receive error messages related to missing permissions. --- # LOG URL: https://docs.valsight.ai/log/ Description: This example calculates the logarithm of input values using a separate node to define the base for each year. **Category:** [Math & numeric](/math-numeric/) ## Overview The **LOG** function **returns the logarithm of a number** (first argument) **with respect to a base** (second argument), while retaining all dimensions. Use this function when you need a logarithm with a specific base rather than the natural logarithm. ## Syntax `LOG('Node1', 'Node2')` ## Parameters | Parameter | Description | Type | Required | | ------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- | | **Value** (`Node1`) | The value for which to calculate the logarithm, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | | **Base** (`Node2`) | The base to use for calculation of the logarithm. The base can also be a standalone number. | Node reference or number | Yes | ## Examples ### Logarithm with a custom base This example calculates the logarithm of input values using a separate node to define the base for each year. **Input node:** `'Value'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 3 | | 2027 | 4.5 | **Input node:** `'Base'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 2 | | 2027 | 2 | **Formula:** `LOG('Value', 'Base')` | Year | LOG Result | | ---- | ---------- | | 2025 | 1 | | 2026 | 1.58 | | 2027 | 2.17 | ## Related | Function | When to use instead | | ------------ | ---------------------------------------------------------------------------------- | | [LN](/ln/) | When you need the natural logarithm instead of a logarithm with a custom base. | | [EXP](/exp/) | When you need exponentiation with base e rather than a logarithmic transformation. | --- # Logging URL: https://docs.valsight.ai/logging/ Description: Logging is separated into application-level logging (security audit log) and webserver-level logging. Logging is separated into application-level logging (security audit log) and webserver-level logging. --- # Logging Configuration URL: https://docs.valsight.ai/logging-configuration/ Description: NOTE: In application versions that use older version of Grails (Prior to Valsight Version 6) the configuration of logback was done using a logback.groovy fil… **NOTE:** In application versions that use older version of Grails (Prior to Valsight Version 6) the configuration of logback was done using a logback.groovy file. This is no longer possible and configuration must be done through an XML file named logback-spring xml. ## External configuration file You can instruct Valsights `Logback` component to use an external configuration file with a system property: ``` $ ./gradlew -Dlogging.config=/Users/me/config/logback-spring.xml bootRun ``` In our distribution folder you can simply add the system property to one of the following files, depends on your environment: * **Windows** * *windowsservice/valsightservice.xml*: simply add the property to the tag * *bin/valsight-server.bat*: Add the property to the already declared variable DEFAULT\_JVM\_OPTS * **Unix** * *bin/valsight-server*: Add the property to the already declared variable DEFAULT\_JVM\_OPTS ### Example logback-spring.xml configuration files:

Configure Logback given the number of days to keep the logs to archived

Configure Logback given the size of the files and the number of logs to archive

Download the attached file and configure manually the following parameter to customize the number of days that a log is kept.

DAYS_LOG_FILE_ARCHIVED (line 8)

Download the attached file and configure manually the following parameters to customize the size of the logging file and the number of versions that you want to archive.

SIZE_LOG_FILE (line 8)

NUMBER_LOG_FILE_ARCHIVED (line 9)

logback_timebase-spring.xml

logback_size-spring.xml

### Useful external links * [Chapter 3: Configuration](https://logback.qos.ch/manual/configuration.html) * [Chapter 4: Appenders](https://logback.qos.ch/manual/appenders.html) * [83. Logging](https://docs.spring.io/spring-boot/docs/2.1.8.RELEASE/reference/html/howto-logging.html) --- # Logging in the Backend URL: https://docs.valsight.ai/logging-in-the-backend/ Description: How admin users configure backend logging levels and download log files from the System Configuration page. As an admin user, go to the System Configuration page (1a). Many parts of the system allow you to increase the log level. *Tip: Get in contact with the Valsight Support team, we are happy to assist.* All output is written to *application.log*. The log files can be downloaded via "Metrics and Logs" from the System Configuration page ![Screen Shot 2017-09-18 at 14.51.24.png](./images/5094205545.png) *(1a) The Log Level configuration* **![Screen Shot 2017-09-18 at 14.51.18.png](./images/5094205530.png)** **(1b) The Log Level configuration** ## Frequently used loggers * com.valsight.authentication.saml * com.valsight.authentication.openidconnect --- # Logical functions URL: https://docs.valsight.ai/logical-functions/ Description: Use this category when you need conditions, comparisons, and branching logic in formulas. Use this category when you need **conditions, comparisons, and branching logic** in formulas. These functions help you build boolean-style expressions, typically represented as `1` or `0`, and use them to select values, create flags, or diagnose unexpected results. ## Start here if you want to: * **Look up a logical function by name**, for example `IF`, `EQ`, `GT`, `AND`, `TRUE`, `FALSE`, or `IS_NA` * **Compare** similar logical functions and understand when to use which one * Find function-specific notes, limits, or troubleshooting ## Not here if you want to: * Write a condition with operators rather than functions, for example the comparisons `>` and `=` or the boolean operators `&&` and `||` → see [Comparisons & boolean operators](/comparisons-boolean-operators/) * Use numeric transformations such as `ROUND`, `ABS` or `MIN`/`MAX`→ see [Math & numeric](/math-numeric/) ## Mental model * Logical functions usually return `1` or `0` across the same dimensionality as their inputs * Conditions are most commonly used inside `IF` to select between two results * Missing values can affect conditions; use `IS_NA` when results look unexpectedly empty or incomplete ## Common patterns | Name | What it does | Formula | | ------------------------------ | ----------------------------------------------------------------------- | ------------------------------------ | | Apply a business rule | Use when you want to cap, floor, or branch values based on a condition. | `IF('Margin' < 0, 0, 'Margin')` | | Create a threshold flag | Use when you want to mark where values exceed a threshold. | `GT('Revenue', 100000)` | | Compare two nodes for equality | Use when you want to create match or mismatch flags for validation. | `EQ('Actuals', 'Plan')` | | Combine multiple conditions | Use when you want to build between-rules or multi-part checks. | `AND(GT('Node', 0), LT('Node', 10))` | | Invert a condition | Use when you want the opposite of an existing rule. | `NOT(EQ('Status', 1))` | | Check for undefined values | Use when you want to flag undefined values before comparisons. | `IS_NA('Node')` | ## Functions in this category **Branching** | Function | Description | | ---------- | ------------------------------------------------------------------------------------- | | [IF](/if/) | Returns value\_if\_true when a condition is true; otherwise returns value\_if\_false. | **Function equivalents of operators** | Function | Description | | ----------------- | ---------------------------------------------------------------------------------------- | | [EQ (=)](/eq/) | Returns 1 (true) if matching row values across two nodes are equal; otherwise 0 (false). | | [NEQ (!=)](/neq/) | Returns 1 (true) where matching values of two nodes are not equal. | | [GT (>)](/gt/) | Returns 1 (true) where the first input is greater than the second. | | [GTE (>=)](/gte/) | Returns 1 (true) where the first input is greater than or equal to the second. | | [LT (<)](/lt/) | Returns 1 (true) where the first node’s values are less than the second. | | [LTE (<=)](/lte/) | Returns 1 (true) where the first node’s values are less than or equal to the second. | | [AND (&&)](/and/) | Returns 1 (true) if both inputs are true; otherwise 0 (false). | | [OR (\|\|)](/or/) | Returns 1 (true) if at least one of the two inputs is true; otherwise 0 (false). | | [NOT](/not/) | Inverts logical values (non-zero becomes 0; zero becomes 1). | | [XOR](/xor/) | Returns 1 (true) if exactly one of two inputs is true (exclusive OR). | **Defined / undefined helpers** | Function | Description | | ----------------- | -------------------------------------------------------------------------------------------- | | [TRUE](/true/) | Returns 1 (true) for every defined value in the node. | | [FALSE](/false/) | Returns 0 (false) for every defined value in the node. | | [IS\_NA](/is-na/) | Returns 1 (true) where values are undefined in the input node’s dimensionality; otherwise 0. | ## Choosing between similar functions **IF vs flags (EQ/GT/LT/…)** * Use `EQ`, `GT`, `LT`, and similar functions when you need a `1`/`0` flag for validation, filtering, or diagnostics * Use `IF` when you want to return one of two result values **EQ vs NEQ** * Use `EQ` to mark matches * Use `NEQ` to mark mismatches **GT/GTE vs LT/LTE** * Use `GT` or `GTE` for above-threshold rules * Use `LT` or `LTE` for below-threshold rules **AND/OR vs XOR** * Use `AND` when all conditions must hold * Use `OR` when any condition may hold * Use `XOR` when exactly one condition should hold **IS\_NA vs FALSE/TRUE** * Use `IS_NA` to detect undefined values * Use `TRUE` or `FALSE` when you want a defined `1` or `0` result across the defined intersections of a node ## Pitfalls & troubleshooting * **IF result looks incomplete:** you probably used the two-argument form. `IF(condition, value)` returns nothing at all where the condition is 0 or missing. Add the third argument to control what those rows get * **Cube size risk:** `IS_NA` expands to a fully expanded cube and can hit maximum cube size * **Conditions look wrong:** check both operands at the same intersection in Data preview; the root cause is often upstream values, not the comparison itself * **Multi-part logic is hard to debug:** split logic into helper nodes, then combine with `AND` or `OR` * **Between logic:** make it explicit with `AND(GTE(...), LTE(...))` rather than relying on a single comparison * **Missing vs zero confusion:** review [Troubleshooting guide](/troubleshooting-guide/) when results look unexpectedly false or empty ## Related * [Comparisons & boolean operators](/comparisons-boolean-operators/): operator syntax for conditions * [Math & numeric](/math-numeric/): use `MIN`/`MAX` for simple caps and floors * [Troubleshooting guide](/troubleshooting-guide/): missing values and unexpected results * [Function catalog](/function-catalog/): full signatures, parameters, and examples --- # Login Page Customization URL: https://docs.valsight.ai/login-page-customization/ Description: The login page can be customized in the global settings under "Login Page Settings". The login page can be customized in the global settings under "Login Page Settings". * Providing a **custom** **image** that is displayed left of the login field. If no image is provided, a default will be used. * Maximum file size: 1 MB * CMYK color space not supported * An optional text message is displayed below the image. You can include and enable links in the text by providing a regular expression defining valid links using the featureFlag setting “*allowedLinksFormat”.* The text is limited to 400 characters and will be truncated if longer. * To edit the regular expression, head to the configuration menu via the cogwheel on the navigation bar; from there go to → Settings → featureFlags.allowedLinksFormat listed below “Appearance” * All links matching the specified regular expression will be shown as clickable links in the Valsight software. This includes the login page, descriptions ins projects/models/workspaces/workflow tiles, node descriptions in tables, node descriptions in the Inspector, node descriptions in the workspace validation, and assumption/line-item descriptions * If you are unsure or otherwise want a standard ‘RegEx’ for this featureFlag, you can use one that allows only Valsight links: ``` (\bhttp?:\/\/(.*valsight)\.com\S*\b) ``` * If external authentication providers using SAML or Open ID Connect are used, the button text can be customized. ![ogin page.JPG](./images/5094211676.jpg) ## OpenID Connect button text and login flows Available since 7.2.5 and 7.3.0. The OpenID Connect configuration in *conf/config.yml* can also carry a default button label, so that a newly installed instance shows the right wording before anyone opens this settings page. The label saved here always wins over that default. The same configuration can add a second, less prominent login option as a link below the OpenID Connect button, for users the primary login flow does not cover. Both are described under [Alternative login flow](/openid-connect/#alternative-login-flow) in the OpenID Connect configuration guide. --- # LOOKUP URL: https://docs.valsight.ai/lookup/ Description: Performs an approximate match lookup in one column and returns the corresponding value from another column. **Category:** [Filtering & data shaping](/filtering-data-shaping/) ## Overview The **LOOKUP** function **performs an approximate match lookup in one column and returns the corresponding value from another column**. Use this function when you need threshold-based or approximate mapping from one value range to another. ## Syntax `LOOKUP('Node1', 'Node2', 'Node3' [, DefaultReturnValue] [, "LevelName"])` ## Parameters | Parameter | Description | Type | Required | Default | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | ------------ | | **Node1** | **Lookup Value**. The value to search for in the index table. | Node reference | Yes | -- | | **Node2** | **Index**. A column of data that is sorted in ascending order. The `LOOKUP` function searches for the value in this range. | Node reference | Yes | -- | | **Node3** | **Return Value**. A range that contains the result. | Node reference | Yes | -- | | **DefaultReturnValue** | The value returned when a lookup value is not found. | Number | No | `-1` | | **LevelName** | The level along which the index values are matched. | Level name | No | `'Sequence'` | ## Watch out * **Important:** the values in the index must be placed in **ascending order (alphabetical sorting)**, otherwise `LOOKUP` might not return the correct value. * The `Index` values have to be sorted as `001`, `002`, `003`, ... instead of `1`, `2`, `3`, ... Otherwise, Valsight will consider, for example, `11` to be smaller than `2`. * The level specified by `LevelName` should not be included in the lookup value table. ## Examples ### Approximate threshold lookup This example looks up a salary against an ordered threshold table and returns the corresponding tax value. The lookup uses one node for the value to search, one node for the sorted index, and one node for the returned result. **Input node:** `'Lookup Value'` | Employee | Salary | | -------- | ------ | | E1 | 50.000 | **Input node:** `'Index'` | Sequence | Threshold | | -------- | --------- | | 0 | 0 | | 1 | 10.000 | | 2 | 30.000 | | 3 | 60.000 | **Input node:** `'Return Value'` | Sequence | Tax | | -------- | ----- | | 0 | 0 | | 1 | 0 | | 2 | 1.000 | | 3 | 2.000 | | 4 | 3.000 | **Formula:** `LOOKUP('Lookup Value', 'Index', 'Return Value')` | Employee | LOOKUP Result | | -------- | ------------- | | E1 | 1.000 | ## Expanding the sequence dimension The sequence dimension is a default dimension that defines the steps of a time value. In rare cases, it can be helpful or even necessary to edit the sequence dimension to support complex scenarios on a monthly level. Additional information on the sequence dimension and how to modify it can be found here: [Configure the Sequence Dimension](/configure-the-sequence-dimension/) ## Related | Function | When to use instead | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------- | | [FILTER](/filter/) | When you want to filter rows by explicit criteria instead of mapping one value range to another through an ordered index table. | | [IF](/if/) | When you want explicit conditional branching logic instead of using an approximate lookup table. | --- # LT (<) URL: https://docs.valsight.ai/lt/ Description: Checking whether one input is less than another **Category:** [Logical functions](/logical-functions/) ## Overview The **LT** function checks whether **the matching row on the first input is less than the matching row in the second input**; true (1) is returned, false (0) otherwise. An undefined value is treated as the number **0** in the comparison; it does not force the result to false. `LT(undefined, 100)` returns 1, because 0 is less than 100. Use this function when you need a 1/0 flag to mark where one input is less than another. ## Syntax `LT('Node1', 'Node2')` `'Node1' < 'Node2'` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | | **Node2** | Second input node. | Node reference | Yes | ## Examples ### Checking whether one input is less than another This example compares two input nodes row by row. The result returns 1 where the first input is less than the second and 0 otherwise. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 400 | | 2026 | 700 | | 2027 | 850 | | 2028 | 500 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 350 | | 2026 | 400 | | 2027 | 850 | | 2028 | 600 | **Formula:** `LT('A', 'B')` | Year | LT Result | | ---- | --------- | | 2025 | 0 | | 2026 | 0 | | 2027 | 0 | | 2028 | 1 | ## Related | Function | When to use instead | | ----------------- | ------------------------------------------------------------------------------------------------------------------ | | [LTE (<=)](/lte/) | When equality should also count as a match instead of requiring the first input to be strictly less. | | [NEQ (!=)](/neq/) | When you want to check for any mismatch instead of specifically testing whether one input is smaller than another. | --- # LTE (<=) URL: https://docs.valsight.ai/lte/ Description: Checking whether one input is less than or equal to another **Category:** [Logical functions](/logical-functions/) ## Overview The **LTE** function checks whether **the matching row on the first input is less than or equal to the matching row in the second input**; true (1) is returned, false (0) otherwise. An undefined value is treated as the number **0** in the comparison; it does not force the result to false. `LTE(undefined, 100)` returns 1, and two undefined cells compare as 0 <= 0, which is also 1. Use this function when you need a 1/0 flag to mark where one input is less than or equal to another. ## Syntax `LTE('Node1', 'Node2')` `'Node1' <= 'Node2'` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | | **Node2** | Second input node. | Node reference | Yes | ## Examples ### Checking whether one input is less than or equal to another This example compares two input nodes row by row. The result returns 1 where the first input is less than or equal to the second and 0 otherwise. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 400 | | 2026 | 700 | | 2027 | 850 | | 2028 | 500 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 350 | | 2026 | 400 | | 2027 | 850 | | 2028 | 600 | **Formula:** `LTE('A', 'B')` | Year | LTE Result | | ---- | ---------- | | 2025 | 0 | | 2026 | 0 | | 2027 | 1 | | 2028 | 1 | ## Related | Function | When to use instead | | ----------------- | ------------------------------------------------------------------------------------------------------------- | | [LT (<)](/lt/) | When equality should not count as a match and the first input must be strictly less. | | [GTE (>=)](/gte/) | When you need to check the opposite direction and include equality for values that are greater than or equal. | --- # Mail Server URL: https://docs.valsight.ai/mail-server/ Description: ON PREMISE This article applies only to Valsight On-Premise. Contact support for Cloud installations. **ON PREMISE** This article applies only to Valsight On-Premise. Contact support for Cloud installations. The application can send emails to users, e.g. notifications on comments or status changes. In order to configure the mail server, add the following to the *config.yml* file. | Configuration key (spring → mail) | Description | Example value | Default value | | --------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------- | | valsightProperties → enabled | Whether the applications e-mail system is enabled or disabled. | true | false | | valsightProperties → defaultFrom | The value "from" address that will be used by all e-mails sent from the application | | | | host | The URL of the e-mail server | [smtp.mymailserver.com](http://smtp.mymailserver.com/) | n/a | | port | Port of the e-mail server | 465 | n/a | | username | Username of a user that is allowed to send e-mails via the e-mail server | myusername | n/a | | password | Password of a user that is allowed to send e-mails via the e-mail server | mypassword | n/a | | properties | Used for configuring additional properties if the mail server requires SSL or TLS connection. More details below. | | | ``` properties: mail.smtp.auth: true mail.smtp.socketFactory.port: 465 mail.smtp.socketFactory.class: javax.net.ssl.SSLSocketFactory mail.smtp.socketFactory.fallback: false ``` \| n/a | **Example server configuration with SSL:** ``` spring: mail: valsightProperties: enabled: true defaultFrom: "do-not-respond@valsight.local" host: smtp.gmail.com username: user@gmail.com password: password port: 465 properties: mail.smtp.auth: true mail.smtp.socketFactory.port: 465 mail.smtp.socketFactory.class: javax.net.ssl.SSLSocketFactory mail.smtp.socketFactory.fallback: false ``` Note that the value 'port' and 'mail.smtp.socketFactory.port' must match. **Example server configuration with TLS:** ``` spring: mail: valsightProperties: enabled: true defaultFrom: "do-not-respond@valsight.local" host: smtp.gmail.com username: user@gmail.com password: password port: 587 properties: mail.smtp.starttls.enable: true mail.smtp.port: 587 ``` Note that the value 'port' and 'mail.smtp.port' must match. --- # Mailing Log Files to the Valsight support URL: https://docs.valsight.ai/mailing-log-files-to-the-valsight-support/ Description: The Valsight Backend keeps track of errors that occurred during the usage of the product. These provide valuable details for our development team. These log … The Valsight Backend keeps track of errors that occurred during the usage of the product. These provide valuable details for our development team. These log files contain no modelling information or data points, other then the currently logged in username. | Filename | Description | | ------------------- | ------------------------- | | log/error.log | Backend Errors | | log/errorJson\*.log | Browser Errors & Warnings | In the admin section, go to the "Metrics" subsection. You find a link to download all log files and metrics. ![Screen Shot 2017-09-22 at 17.57.36.png](./images/5094205754.png) --- # Manage Users and Groups URL: https://docs.valsight.ai/manage-users-and-groups/ Description: As an administrator, open the System Configuration and find the users section. Administrators manage users and groups from the admin UI: adding, editing and deleting users, configuring how each one logs in, and assigning them to groups. ## Managing users As an administrator, open the System Configuration and find the users section. In the users section you find options to add, edit, and delete users of the system. Opening the detail page for a user allows you to define its rights in the system. ![Login doku.PNG](./images/5094194643.png) **Login methods** Valsight supports four login methods. Login via username and password, login via an API key, login via SAML authentication and login via an OpenID Connect (Single sign-on). The API key method enables access to data in Valsight, whereas the OpenID connect and SAML method enable access to Valsight via the corporation accounts of users. Depending on the user, select those methods applicable. ## Managing groups Like managing users, as an administrator you will find an option *Groups* as part of the System Configuration page. Here you can list, create, and delete groups or assign users to groups. ![System\_Configuration\_-\_Valsight.png](./images/5094192887.png) ## Access to projects, models and workspaces Set the rights for individual projects for the user: [Project Rights](/project-rights/) --- # Managing Access Rights URL: https://docs.valsight.ai/managing-access-rights/ Description: The redesigned Access Rights screen lets you review and change who can see and edit projects, models, workspaces, data classes, and presentations from a single matrix. The redesigned Access Rights screen Beta lets you manage who can see and change projects, models, workspaces, data classes, and presentations from a single matrix. > This screen is a beta. Turn it on for yourself on your **User Profile** page with the **Use the new access rights view** switch. Access-rights links throughout the application then open the new view; the previous view stays reachable by direct link. ## Turning on the new view 1. Open your **User Profile** (personal configuration). 2. Enable **Use the new access rights view** and save. 3. Access-rights links across the application now open the redesigned screen. The switch is per user — each person turns it on for themselves, and it is off by default. ## The access rights matrix The screen opens on a matrix of **users and groups** against **objects**. A cell shows the access a holder has to that object. A compact filter bar across the top decides what the matrix contains: ![The Access Rights matrix: a filter bar with Projects, Users and Groups, and Categories, a Pivot Table button and a color legend, above a table of users and groups against a project column showing each holder's access, with Global Admin badges](./images/access-rights-matrix.png) * **Projects** — pick one or more projects. You can limit the list to **Only Projects I Administer** and **Show Hidden Projects**. * **Users and Groups** — filter the holders shown, by **All**, **Users**, or **Groups**, or search by name. * **Categories** — choose which kinds of objects appear: **Projects**, **Models**, **Workspaces**, **Data Classes**, and **Presentations**. Until you select at least one project and one category, the matrix stays empty and prompts you to make a selection. Reading the matrix: * **Holder badges:** each user or group shows its type — **User**, **Group**, or **Global Admin**. * **Object-specific labels:** a cell's label depends on the object — a project reads **Can use** or **Project admin**, a model **Read-Only** or **Can edit**, a workspace **Limited access** or **Full access**. **No access** means none. See [Access Rights](/access-rights/) for what each level allows. * **Legend:** explains the colors. * **Pivot Table:** swaps the axes, so holders and objects trade places between rows and columns. ## Editing access from a cell Select a cell to open its editor, where checkboxes set the holder's **direct** access to that object. The editor also explains the access it cannot change directly: ![The cell editor popover for a user's access to a project, with Can use and Project admin checkboxes, a Why This Access? section showing the effective access and its explanation, and Edit All Users & Groups, Cancel, and Save actions](./images/access-rights-cell-editor.png) * **Why This Access?** expands a plain-language explanation of the holder's **Effective Access** and where it comes from — for example *Granted directly*, *Via group membership*, *Project administrator*, or *Blocked: no access to the parent project*. * When a holder already has access indirectly, the editor notes that the checkboxes set direct access only. * When a direct grant currently has no effect — because the user has no access to the parent project, or their user type does not permit it — the editor says so. ## Editing all access for a user or group Choose **Edit Access Rights** on a holder to open **Access Rights of '*holder*'**, which lists every object that holder can reach. * **Grouped and sortable:** objects sit in collapsible cards by category and project; sort the objects within a card, sort the cards themselves, and use **Expand All** or **Collapse All**. * **Filter:** narrow the objects by name. * **No cascade:** **permissions don't cascade to linked objects** — granting access to a model does not grant access to its submodels or project. Set those separately. ![The per-holder editor dialog titled Access Rights of 'admins', with a "Permissions don't cascade to linked objects" warning, a filter box, and a collapsible Projects card listing objects with Can use and Project admin checkbox columns](./images/access-rights-holder-editor.png) ## Editing all access to one object Choose **Edit Access to This Object** to open **Access to '*object*'**, which lists the users and groups with access to that object so you can adjust them together, with a filter and **Select all**. ![The per-object editor dialog for a project, listing users and groups with Can use and Project admin checkbox columns, a filter box, All/Users/Groups tabs, a Select all row, and Cancel and Save actions](./images/access-rights-object-editor.png) * **Model links:** removing read access to a model can also remove access to its linked and parent models. * **Presentations:** owner-only for writing — the owner always keeps write access. ## Changing many cells at once Select several cells to open the bulk editor, **Edit Access for *N* Cells**. * **Three-way control:** for each right, choose **Grant**, **No change**, or **Revoke**. The editor shows whether the selected cells currently all, partly, or none have that access. * **Write implies read:** granting write access also grants read. * **Apply:** writes the change to every selected cell. Objects you cannot administer are excluded and called out, and a selection larger than the dialog's limit asks you to narrow it. ## Confirmations and safeguards * **Reaching an object:** when a grant needs project access to take effect, a confirmation lists the users who will be added to the project so they can reach the object — you can **Add to Project & Apply** or **Apply Without Adding to Project**. * **Your own access:** removing your own access — directly or through a group you belong to — prompts **You Are Removing Your Own Access**, because the affected objects then disappear from your table. Confirm with **Remove Anyway**. * **Out-of-date values:** if some rights cannot be refreshed, the screen warns that the values shown may be out of date and offers **Retry**. ## Related * [Access Rights](/access-rights/): what each access level allows per object. * [Manage users and groups](/manage-users-and-groups/): create the users and groups you assign access to. The matrix holders are users and groups; object categories are `projects`, `models`, `simulationWorkspaces`, `dataPermissionClasses`, and `workspaceSnapshots`. A cell's effective access is composed of direct grants, group membership, and project role; the cell editor changes direct access only. The bulk editor's per-right control maps to grant / no-change / revoke intents, and write implies read. The opt-in is the `useNewAccessRights` flag on the app user, toggled on the user profile. --- # Managing Exports URL: https://docs.valsight.ai/managing-exports/ Description: - Each export and its versions are stored in Valsight for seven days by default, so that you can download, share or revisit them at a later date, but still m… Manage existing exports: expiry dates, versioning, editing, deletion, and the filters that keep a long list organized. ![image-20240606-163447.png](./images/5559386124.png) ## Expiry date ![image-20240606-163531.png](./images/5559156774.png) * Each export and its versions are stored in Valsight for seven days by default, so that you can download, share or revisit them at a later date, but still maintain a tidy export manager. * If you create a new version of an export, the new version will also be stored for seven days, without affecting the expiry date of the previous version (see above, “Versioning”). * If you delete all versions of an export, the export itself will also be deleted. * **Shared exports are stored indefinitely by default.** * An export can be saved indefinitely by selecting the respective option during the creation or in the edit dialogue. If selected, all versions of the export will be saved indefinitely, regardless if the export is shared. * If the export setting is changed from unlimited back to limited, the expiry date of the export and all it's versions is reset to seven days. * This is not possible while the export is shared. On a shared export, ‘Save export indefinitely’ is ticked and greyed out, with the note that shared exports must be saved and have to be unshared first. Unsharing is therefore the only way to let a shared export expire and free the storage it uses. ## Editing exports * **Deleting:** Any export itself can be deleted just like its Versions through the three-dot menu on the right. Deleting an export with multiple versions will result in the deletion of all versions of this export. * **Deleting shared exports:** If an export is shared with another project, deleting the export or a version will result in all projects with previous access to this export to no longer be able to import it as a data source. > Deleting an export does not revoke access to already shared and imported scenarios. If another project has already imported a scenario, deleting it from the export manager will not result in the deletion of this scenario as a data source in the destination project. * **Editing:** As well as deleting exports and versions, you can change the name and description of both the export and the versions at any time using the three-dot menu. ![image-20240606-163625.png](./images/5558960156.png) **Filtering:** To help you navigate and manage your exports, you can sort the list by a number of factors, such as sharing, creation date, or number of versions. ![image-20240606-163831.png](./images/5559058463.png) ## Related * [Export Manager](/export-manager/) --- # Math & numeric URL: https://docs.valsight.ai/math-numeric/ Description: Use this category when you need numeric transformations and helpers in formulas. Use this category when you need **numeric transformations and helpers** in formulas. These functions change values row-wise and support tasks such as rounding, caps and floors, powers, roots, logarithms, and element-wise adjustments. ## Start here if you want to: * Use **numeric helpers** such as rounding, caps/floors, sign, or modulo * Apply **an element-wise constant change** * Use **powers, roots, or logarithms** * Use controlled **multiplication or division** with optional mismatch validation ## Not here if you want to: * Reshape output granularity → see [Dimensionality & hierarchies](/dimensionality-hierarchies/) * Use conditions, comparisons, or branching logic → see [Logical functions](/logical-functions/) * Use time comparisons or projections → see [Compare periods](/compare-periods/) or [Rollforward & time series](/rollforward-time-series/) ## Mental model * Most functions in this category work row-wise and usually keep the input shape * Constants are 0-dimensional; if `+ 1` causes unexpected aggregation effects, use `ADDEACH` for an explicit element-wise adjustment ## Common patterns | Name | What it does | Formula | | ------------------------------------ | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | | Add a constant to every cell | Use when you want an element-wise change without aggregation side effects. | `ADDEACH('Sales', 1)` | | Compute a display-style ratio | Keeps only the shared dimensionality of both inputs. `RATIO` must be an end node. | `RATIO('Gross Profit', 'Revenue')` | | Cap / floor values | Use when you need simple numeric thresholds without `IF`. | `MAX('Margin', 0)` or `MIN('Node1', 'Node2')` | | Round for reporting | Use when you need stable rounding for display or downstream steps. | `ROUND('Revenue')` | | Safe divide or multiply | Use when you want clearer mismatch feedback instead of raw `/` or `*`. | `DIVIDE('Node1', 'Node2', "FailOnMissingFirst")` | | Transform with logs, power, or roots | Use when your method requires non-linear scaling. | `LN('Node')`, `LOG('Node1', 'Node2')`, `POWER('Node1', 'Node2')`, `SQRT('Node')` | ## Functions in this category | Function | Description | | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | [ABS](/abs/) | Returns the absolute value of each value in the node. | | [ADDEACH](/addeach/) | Adds the specified amount to each row in the node without aggregation. | | [DIVIDE](/divide/) | Divides the first input by the second with optional validation that provides detailed errors on mismatches. | | [MULTIPLY](/multiply/) | Multiplies inputs with optional validation that provides detailed errors on mismatches. | | [EXP](/exp/) | Calculates *e* (≈2.718) raised to the power of the input values. | | [FACT](/fact/) | Returns the factorial of each input value. | | [LN](/ln/) | Returns the natural logarithm of the input. | | [LOG](/log/) | Returns the logarithm of a value with respect to a specified base. | | [MAX](/max/) | Returns the row-wise maximum of two nodes. | | [MIN](/min/) | Returns the row-wise minimum of two nodes. | | [MOD](/mod/) | Returns the remainder after dividing the first input by the second. | | [POWER](/power/) | Raises values from the first node to exponents from the second input. | | [RATIO](/ratio/) | Divides the first node by the second while retaining only joint dimensions. Must be an end node; the result cannot be used in further calculations. | | [ROUND](/round/) | Rounds each value to a specified number of decimal digits. | | [SIGNUM](/signum/) | Returns the sign of each number: 1 for positive, −1 for negative, 0 for zero. | | [SQRT](/sqrt/) | Returns the square root of each value in the node. | ## Choosing between similar functions **ADDEACH vs** `+` with a constant * Use `ADDEACH` when you want an explicit element-wise adjustment * Use `+` with a constant only if you intentionally want standard arithmetic behavior with a 0-dimensional value **DIVIDE/DIVISION (/) vs RATIO** * Use `DIVISION (/)` for standard division * Use `DIVIDE` when you want standard division with optional mismatch validation * Use `RATIO` when you want a ratio that keeps only joint dimensions for display purposes; `RATIO` must be an end node **MIN/MAX vs IF** * Use `MIN`**/**`MAX` for simple caps and floors * Use `IF` when the rule depends on broader conditional logic **LN vs LOG vs EXP** * Use `LN` for natural logarithm * Use `LOG` when you need a specific base * Use `EXP` for exponentiation with base `e` ## Pitfalls & troubleshooting * **Unexpected aggregation after adding a constant:** replace `+ 1` style adjustments with `ADDEACH` * RATIO **cannot be reused downstream**: if the result must feed other nodes, use `/` or `DIVIDE` and set aggregation appropriately * **Division looks wrong:** check denominators for zero or missing values and validate both inputs at the same intersections * **LN/LOG/SQRT return missing results:** confirm the input domain (negative values or zeros where not supported) * **Rounding drift**: apply `ROUND` late, not in intermediate calculations ## Related * [Operators](/operators/): arithmetic used around numeric functions * [Logical functions](/logical-functions/): conditions and branching with `IF` * [Troubleshooting guide](/troubleshooting-guide/): missing values, alignment issues, and unexpected shape changes * [Function catalog](/function-catalog/): full signatures, parameters, and examples --- # MAX URL: https://docs.valsight.ai/max/ Description: The MAX function returns the maximum of matching values from two inputs. Both inputs must have either the same dimensionality or one input must be a number, in which case the result has the dimensionality of the other input. **Category:** [Math & numeric](/math-numeric/) ## Overview The **MAX** function **returns the maximum of matching values from two inputs**. Both inputs must have either the same dimensionality or one input must be a number, in which case the result has the dimensionality of the other input. Use this function when you need the row-wise maximum of two nodes or when you want to apply a lower threshold (floor) to a node. ## Syntax `MAX('Node1', 'Node2')` **Example usage:** `MAX('Revenue', 0)` ## Parameters | Parameter | Description | Type | Required | | --------- | -------------------------------------------------------------------------------------------- | ------------------------ | -------- | | **Node1** | First input, specified using the node name in single quotes (e.g.`'Revenue'`) or a number | Node reference or number | Yes | | **Node2** | Second input, specified using the node name in single quotes (e.g.`'Threshold'`) or a number | Node reference or number | Yes | ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------------------------------------------------------------ | | Dimensionality | Same as the input with levels. If one input is a constant (number), the result has the dimensionality of the other input. | | Values | For each matching row, the higher of the two values is returned. A row that exists in only one input keeps that input's value. | | Row count | The union of both inputs. A row present in only one of them is kept, not dropped. | ## Watch out * If both inputs have levels, they **must have the same dimensionality**. Unlike multiplication or division, MAX does not perform dimension union or intersection. * One input can be a **constant number** (e.g. `0`, `100`). In that case, the constant is compared against every row of the other input. * Same dimensionality does **not** mean the same level values. Only the level names have to match. Where one input has a row that the other does not, MAX returns the value that is there rather than dropping the row, so the result can have more rows than either input. ## Examples ### Row-wise maximum across two inputs This example shows MAX applied both to two input nodes and to a node combined with a fixed numeric threshold. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 32 | | 2026 | -42 | | 2027 | -17 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 41 | | 2026 | 12 | | 2027 | -25 | **Formula:** `MAX('A', 'B')` | Year | MAX Result | | ---- | ---------- | | 2025 | 41 | | 2026 | 12 | | 2027 | -17 | **Formula:** `MAX('A', 7)` | Year | MAX Result | | ---- | ---------- | | 2025 | 32 | | 2026 | 7 | | 2027 | 7 | ### Using MAX as a floor (clamp negative values to zero) A common pattern: use `MAX('Node', 0)` to ensure no negative values appear in the result. **Input node:** `'Margin'` | Year | Value | | ---- | ----- | | 2025 | 15 | | 2026 | -8 | | 2027 | 22 | | 2028 | -3 | **Formula:** `MAX('Margin', 0)` | Year | MAX Result | | ---- | ---------- | | 2025 | 15 | | 2026 | 0 | | 2027 | 22 | | 2028 | 0 | Negative margins are replaced with 0. Positive margins are kept as-is. ## Related | Function | When to use instead | | ------------ | -------------------------------------------------------------------------------------- | | [MIN](/min/) | When you need the row-wise minimum of two nodes or thresholds instead of the maximum. | | [ABS](/abs/) | When you need absolute values of one node rather than a comparison between two inputs. | --- # Migration Guide URL: https://docs.valsight.ai/migration-guide/ Description: The whole configuration moves from the grails section into the spring section. The mail configuration moved out of the `grails` section of *config.yml* and into the `spring` section. This page maps every changed property to its new location. ## Property mapping | Old value | New value | Notes | | -------------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `grails.mail.*` | `spring.mail.*` | The whole configuration moves from the `grails` section into the `spring` section. | | `grails.mail.disabled` | `spring.mail.valsightProperties.enabled` | **Boolean reversal.** The property moved under `valsightProperties` and changed from `disabled` to `enabled`. It still defaults to disabled. | | `grails.mail.default.from` | `spring.mail.valsightProperties.defaultFrom` | Property `from` moved and was renamed to `defaultFrom`. | | `grails.mail.props` | `spring.mail.properties` | Property `props` was renamed to `properties`. | All other properties are the same, with the same behaviour. --- # MIN URL: https://docs.valsight.ai/min/ Description: The MIN function returns the minimum of matching values from two inputs. Both inputs must have either the same dimensionality or one input must be a number, in which case the result has the dimensionality of the other input. **Category:** [Math & numeric](/math-numeric/) ## Overview The **MIN** function **returns the minimum of matching values from two inputs**. Both inputs must have either the same dimensionality or one input must be a number, in which case the result has the dimensionality of the other input. Use this function when you need the row-wise minimum of two nodes or when you want to apply an upper threshold (cap) to a node. ## Syntax `MIN('Node1', 'Node2')` **Example usage:** `MIN('Revenue', 1000)` ## Parameters | Parameter | Description | Type | Required | | --------- | -------------------------------------------------------------------------------------------- | ------------------------ | -------- | | **Node1** | First input, specified using the node name in single quotes (e.g.`'Revenue'`) or a number | Node reference or number | Yes | | **Node2** | Second input, specified using the node name in single quotes (e.g.`'Threshold'`) or a number | Node reference or number | Yes | ## Output shape | Aspect | Behavior | | -------------- | ----------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as the input with levels. If one input is a constant (number), the result has the dimensionality of the other input. | | Values | For each matching row, the lower of the two values is returned. A row that exists in only one input keeps that input's value. | | Row count | The union of both inputs. A row present in only one of them is kept, not dropped. | ## Watch out * If both inputs have levels, they **must have the same dimensionality**. Unlike multiplication or division, MIN does not perform dimension union or intersection. * One input can be a **constant number** (e.g. `0`, `100`). In that case, the constant is compared against every row of the other input. * Same dimensionality does **not** mean the same level values. Only the level names have to match. Where one input has a row that the other does not, MIN returns the value that is there rather than dropping the row. This matters when you use MIN as a cap between two nodes: rows the cap node is missing come through **uncapped** instead of disappearing. A constant cap has no gaps and is not affected. ## Examples ### Row-wise minimum across two inputs This example shows MIN applied both to two input nodes and to a node combined with a fixed numeric threshold. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 32 | | 2026 | -42 | | 2027 | -17 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 41 | | 2026 | 12 | | 2027 | -25 | **Formula:** `MIN('A', 'B')` | Year | MIN Result | | ---- | ---------- | | 2025 | 32 | | 2026 | -42 | | 2027 | -25 | **Formula:** `MIN('A', 12)` | Year | MIN Result | | ---- | ---------- | | 2025 | 12 | | 2026 | -42 | | 2027 | -17 | ### Using MIN as a cap (clamp values to an upper limit) A common pattern: use `MIN('Node', threshold)` to ensure no value exceeds a defined maximum. **Input node:** `'Discount Rate'` | Year | Value | | ---- | ----- | | 2025 | 0.05 | | 2026 | 0.12 | | 2027 | 0.08 | | 2028 | 0.25 | **Formula:** `MIN('Discount Rate', 0.15)` | Year | MIN Result | | ---- | ---------- | | 2025 | 0.05 | | 2026 | 0.12 | | 2027 | 0.08 | | 2028 | 0.15 | Values above 15% are capped at 0.15. Values already below the threshold are kept as-is. ## Related | Function | When to use instead | | ------------ | -------------------------------------------------------------------------------------- | | [MAX](/max/) | When you need the row-wise maximum of two nodes or thresholds instead of the minimum. | | [ABS](/abs/) | When you need absolute values of one node rather than a comparison between two inputs. | --- # Mixed Charts URL: https://docs.valsight.ai/mixed-charts/ Description: A mixed chart lets you show each data series differently, so bars and lines can sit in the same chart. A mixed chart shows different data series in different ways within the same chart. Most of your data can be stacked bars while one data series runs across them as a line, which is the usual way to show a benchmark next to a breakdown. ## What it is When you add a mixed chart, everything in it starts out as a bar. Nothing is set up for you beyond that. You then pick individual data series and change how each one is shown, choosing between **Line**, **Bar**, **Area** and **Spline**. How a data series is shown also decides whether it stacks, and **Line** is the exception: a line never stacks and always draws in front, whatever **Stacked** is set to. That is what makes the chart useful, because you can show one scenario as a single line and read it against another scenario's stacked breakdown behind it. The table under **Configuration** has the rule for each of the four options. ![Revenue mixed chart: simulation and delta to target stacked as bars per year, with the target drawn across them as a red line](./images/mixed-chart.png) ## When to use it * You want a total and its breakdown in one picture, rather than two charts side by side. * You want to compare two scenarios where one acts as the benchmark and the other is broken down into its parts. * You want to show a figure that is measured differently, such as a target or a rate, next to the amounts it relates to. Use a **column chart** or a **stacked column chart** instead if every data series should look the same. The mixed chart only earns its place when at least one data series needs to stand apart from the others. ## Configuration ### Change how a data series is shown **Show as** is not in the chart editor itself. It sits one level down, inside the **Data Series** dialog: 1. Select the chart. The chart editor opens on the right. 2. Scroll to the **Formatting** section and click **Data Series**. The **Style Data Series and X-Axis** dialog opens. 3. Stay on the **Data Series** tab and tick the data series you want to change in the list on the left. You can tick several at once. 4. Under **Show as**, choose **Line**, **Bar**, **Area** or **Spline**. 5. Click **Confirm**. ![The Show as options in the Data Series dialog, with one of three data series ticked in the list on the left](./images/data-series-dialog.png) | Option | What you get | | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Line** | A straight line between the values. Never stacks, whatever **Stacked** is set to, and is drawn in front of everything else. | | **Bar** | A vertical bar. Stacks together with the other bars. | | **Area** | A filled shape under the line of values. Stacks together with the other areas, separately from the bars. | | **Spline** | A curved line between the values, for a smoother shape than **Line**. Also drawn in front, but unlike **Line** it stacks with the other splines when **Stacked** is on. | Colors and value labels are set in the same dialog, per data series. See [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/). ### Stack the bars The **Stacked** checkbox sits next to the chart type buttons in the chart editor. Switch it on to stack the bars on top of each other, and off to place them next to each other. To label the total of each stack, see [Stacking and Stack Totals](/stacking-and-stack-totals/). ## Good to know * **Setting several data series to bars does not stack them.** Stacking is the separate **Stacked** checkbox, and without it the bars sit side by side. * **You cannot find Show as:** it is inside the **Data Series** dialog, not in the chart editor itself, and only on the **Data Series** tab. If the **X-Axis** tab is open you will not see it. * **A figure measured differently needs its own axis.** A rate or a target read against the same axis as the amounts around it will look flat or swamp them. Put it on a second axis: see [Axis Scales and Decimals](/axis-scales-and-decimals/). * **Spline is not a smoother Line.** Both draw in front, but splines stack with each other, where a line never stacks. For a benchmark that has to stay out of the stack, use **Line**. ## Related * [Compare a Total with a Breakdown](/configure-flexible-scenario-comparisons-in-a-single-chart/): the step-by-step version of the benchmark-line-over-stacked-bars layout, including how to set up the axes for it. * [Axis Scales and Decimals](/axis-scales-and-decimals/): give a data series its own axis when its unit differs. * [Chart Types](/chart-types/): the other chart types you can choose from. --- # MOD URL: https://docs.valsight.ai/mod/ Description: Use when you need the remainder after dividing one value by another, for example for bucket logic or periodic patterns. **Category:** [Math & numeric](/math-numeric/) ## Overview The **MOD** function **returns the remainder value after performing a division operation between two nodes**. The input values are `'Number'`, `'Divisor'`, and an optional validation option. If no validation is required, the same result can be achieved using the `%` symbol, for example `'Number' % 'Divisor'`. The operation is performed along the linked levels between the nodes. Use this function when you need the remainder after dividing one value by another, for example for bucket logic or periodic patterns. ## Syntax `MOD('Number', 'Divisor' [, "Validation"])` ## Parameters | Parameter | Description | Type | Required | Default | | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | ---------------- | | **Number** | Input node. | Node reference | Yes | -- | | **Divisor** | Input node. | Node reference | Yes | -- | | **Validation** | Causes the node executing the function to error with a message explaining why if conditions are not met. Note that using validation can affect performance. | Keyword | No | `"NoValidation"` | **Validation options:** * `"NoValidation"`: Behaves the same as using the `%` symbol. This is the default. * `"FailOnMissingFirst"`: The calculation fails if any row in `'Number'` is not matched with any row in `'Divisor'`. * `"FailOnMissingSecond"`: The calculation fails if any row in `'Divisor'` is not matched with any row in `'Number'`. * `"FailOnMissing"`: Combines `"FailOnMissingFirst"` and `"FailOnMissingSecond"` validation options. ## Watch out * The result is the **remainder** of the division and keeps the decimal places of the inputs: `10.5 % 3` is `1.5`. You only get whole numbers back if both inputs are whole numbers. * A missing **Number** counts as 0, so the row still appears in the result with the value 0. A missing or zero **Divisor** removes the row. ## Examples ### Modulo with missing matches and division by zero This example shows how `MOD` behaves when rows are matched normally, when a divisor is zero, and when rows are missing on one side. **Input node:** `'Node A'` | Year | Volume | | ---- | ------ | | 2025 | 10 | | 2026 | 10 | | 2027 | 5 | | 2028 | 0 | | 2029 | 7 | **Input node:** `'Node B'` | Year | Volume | | ---- | ------ | | 2025 | 6 | | 2026 | 10 | | 2027 | 0 | | 2028 | 5 | | 2030 | 3 | **Formula:** `MOD('Node A', 'Node B')` **Equivalent to:** `MOD('Node A', 'Node B', "NoValidation")` **Equivalent to:** `'Node A' % 'Node B'` | Year | MOD Result | | ---- | ---------- | | 2025 | 4 | | 2026 | 0 | | 2028 | 0 | | 2030 | 0 | **Note:** The year `2027` has no result because it is not possible to perform `5 % 0`, that is, divide by 0. The year `2029` has no result either: `'Node B'` has no value there, and a missing divisor removes the row. `2030` is the other way round, missing in `'Node A'`. A missing number is treated as 0, so the row survives with the result `0`. ## Related | Function | When to use instead | | -------------------------- | --------------------------------------------------------------------------------- | | [DIVISION (/)](/division/) | When you need the quotient of a division instead of the remainder after division. | | [ROUND](/round/) | When you want to round numeric values instead of calculating a remainder. | --- # Model Editor UI URL: https://docs.valsight.ai/model-editor-ui/ Description: The Model Editor is the central screen for building and maintaining models in Valsight. The Model Editor is the central screen for building and maintaining models in Valsight. The screen is organized around one core principle: the **canvas is the source of selection**, and the surrounding areas update to reflect what is currently selected. The **header** and **action bar** remain stable and provide global actions and navigation, while the **Function Editor** and **Context Panel** change depending on whether a node, an annotation or nothing is selected. **It includes:** * A global **header** for model-wide context and actions * A **canvas** where the model graph is displayed * An **action bar** at the bottom for navigation, selection and creation * A **function editor** for node calculations * A right-side **context panel** for model, node and annotation configuration ## Layout at a glance ![The Model Editor with its five areas numbered: header, canvas, action bar, function editor and context panel](./images/6642302979.png) **Legend** 1. [Header](#header) 2. [Canvas](#canvas) 3. [Action Bar](#action-bar) 4. [Function Editor](#function-editor) 5. [Context Panel](#context-panel) ## Header ![The Model Editor header, with the model selector, the project horizon, validation status, and the Validation Node Checkup and Upload Data actions](./images/6627229733.png) The header provides global context and actions for the current model. It remains visible while you work on the canvas. **Used for** * Changing the active model context * Providing model-wide actions and status indicators **Contains** * Model selector to switch between models * Project horizon indicator * Validation status and validation-related actions * Collaboration indicators (for example, active users) * Global actions (for example, validating the model or uploading data) ## Canvas ![The Model Editor canvas showing a P\&L driver tree, with the dimension legend, minimap and action bar around it](./images/6627229730.png) The canvas is the main area where your model is displayed as a node graph. It shows nodes, connections, and annotations. **Used for** * Visualizing and arranging model structure * Inspecting how nodes and drivers relate to each other **Contains** * Nodes representing metrics, drivers, and calculations * Connectors representing dependencies between nodes * Annotations used to document structure and intent **Optional overlays** The canvas supports optional overlays that can be shown or hidden in the **Model** section of the Context Panel: * **Minimap:** Provides a compact overview of the full model layout * **Dimension legend:** Shows which dimensions are used by nodes in the current model. It is only available while **Show Dimension Levels** is on. With that setting off the legend toggle is greyed out, and its tooltip reads ‘Activate “Show Dimension Levels” to enable the legend.’ See [Level Indicators on Nodes](/level-indicators-on-nodes/) ## Action Bar ![The action bar, grouped into Navigate, Select and Create controls](./images/6627229727.png) The action bar is a persistent control strip at the bottom of the Model Editor. It provides quick access to navigation, selection and creation actions. **Used for** * Navigating the model view * Controlling selection and layout behavior * Creating new elements on the canvas **Contains** * Navigation controls such as search, fit-to-view, and zoom * Selection controls such as layout lock and selection mode * Creation controls for adding nodes or annotations **Layout lock** Layout lock freezes the position of everything on the canvas: nodes, annotations and swimlane dividers alike. Nothing can be dragged while it is on, but everything else stays available, so you can still select nodes, edit them and draw connectors. Use it to read or present a model without nudging its layout by accident. The button carries a padlock icon, and its tooltip reports the current state as ‘Layout lock: On’ or ‘Layout lock: Off’. It starts **off** every time the Model Editor is opened, because the setting is not saved: locking the layout in one session does not lock it in the next. It appears only if you have the rights to edit the model. > **If a node will not move, check layout lock first.** It is the most common reason a model refuses to be rearranged, and nothing else on the canvas behaves differently while it is on. ## Function Editor ![The Function Editor for the Net Profit node, showing its formula, the available levels and the Data Preview button](./images/6627229721.png) The Function Editor is the area used to view and define the calculation logic of a selected node. It is displayed in the Model Editor below the header when a node is selected. **Used for** * Viewing and editing a node’s calculation expression * Reviewing node-specific context relevant to the calculation **Contains** * Node name and contextual metadata * Controls to save or discard changes * Undo and redo controls * Shortcut buttons for connecting data or inserting functions and levels * Access to data preview for the selected node * A display of available levels for the selected node **Contextual behavior** * Updates when a different node is selected * Not shown when no node is selected or when an annotation is selected ## Context Panel **Model Tab** ![The Context Panel's Model tab, with the Node Display and Canvas Display toggles and the connector style options](./images/6627229718.png) **Node Tab** ![The Context Panel's Node tab, with the node's name, description, colour and unit, an Allow Simulation toggle, and collapsed Aggregation, Validation and Advanced Settings sections](./images/6627229715.png)![The Node tab's Validations view, reporting that no issues were found](./images/6627229712.png) **Annotation Tab** ![The Context Panel's Annotation tab, with a text edit button and the annotation colour palette](./images/6627229709.png) The Context Panel is the right-side configuration area of the Model Editor. It displays contextual settings and controls based on the current selection. **Used for** * Reviewing and adjusting settings related to the current context (model, node, or annotation) * Viewing node validations **Contains** * **Model mode:** Model-level layout and display settings when no element is selected * **Node mode:** Node configuration and a validations section when a node is selected * **Annotation mode:** Annotation configuration when an annotation is selected ## Related * [Nodes](/nodes/) * [Baselines](/working-with-different-model-baselines/) --- # Model Tree URL: https://docs.valsight.ai/model-tree/ Description: Show the model behind the numbers on a worksheet, as a graph of connected nodes carrying values per scenario. A model tree draws the nodes of the underlying model as a graph on the worksheet, so you can show how a figure is arrived at rather than only what it is. In the chart type selection it is called **Tree**, under **Others**. ## What it is Each node is drawn as a box: its name and unit in the header, then one row per period with the value. Connectors show which nodes feed which, so the chain from the drivers to the top figure is visible. Values can be shown for several scenarios at once. ![A model tree with gross profit broken down into revenue and cost nodes, each node listing values per year](./images/model-tree.png) The tree is a view of the model, not a separate drawing. It follows the model's structure, so it changes when the model changes. ## When to use it * You want to explain the cause and effect behind a number, not just present the number. * You are walking an audience through a model for the first time. * You want to show where an assumption enters the calculation. Use a **[bridge](/bridges/)** instead when the question is why two values differ, and a **[waterfall](/bridges/)** when you want a build-up rather than the whole structure. ## Configuration Much of what a model tree looks like comes from the nodes themselves, in the model editor. The chart editor adds a **Tree Settings** section of its own, which applies to that one chart: | Setting | Where it lives | What it does | | ----------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Default Scale** | Node advanced settings | Sets the scale a node's numbers are shown at, in every chart including the tree. See [Default Scale Settings in Nodes](/default-scale-settings-in-nodes/). | | **Sort key** | Node advanced settings | Sets the order the nodes appear in. See [Sort Key Settings in Nodes](/sort-key-settings-in-nodes/). | | **Hide in workspace** | Node advanced settings | Excludes a node from model tree charts. See [Advanced Node Settings](/advanced-node-settings/). | | **Hide technical Nodes** | Workspace setting | Overrides **hide in workspace** for the whole workspace. | | **Show key figures** | Chart editor, Tree Settings | Shows or hides the key figures inside each node box. | | **Show aggregation type** | Chart editor, Tree Settings | Shows or hides each node's aggregation type in the node box. | | **Hide empty nodes** | Chart editor, Tree Settings | Leaves nodes that carry no values out of this chart. | | **Show assumption influence** | Chart editor, Tree Settings | Marks the nodes an active assumption feeds into. | The four **Tree Settings** toggles sit in the chart editor and only affect the chart you are editing. The node settings above them affect every chart the node appears in. ## Good to know * **A node hidden in the workspace will not appear.** Nodes marked **hide in workspace** are left out of model tree charts by default. Switch **Hide technical Nodes** off for the workspace to bring them back. This is not the same control as **Hide empty nodes**, which is a chart setting and drops nodes that have no values rather than nodes marked technical. * **Hiding or coloring connectors does not carry over.** Those node settings affect the model editor, not the tree chart on a worksheet. * **Unformatted large numbers are a node setting, not a chart setting.** A tree puts nodes of very different magnitudes side by side, and the chart's own scale applies to all of them at once, so raising it rounds the small values to zero. Set each node's **[Default Scale](/default-scale-settings-in-nodes/)** instead. * **Nodes with no sort key sort by name.** That is why costs sort above revenue. Give the nodes sort keys to set a deliberate order, and note that the ordering runs among siblings rather than across the whole tree. ## Related * [Sort Key Settings in Nodes](/sort-key-settings-in-nodes/): controlling the order nodes appear in. * [Default Scale Settings in Nodes](/default-scale-settings-in-nodes/): scaling a node's numbers, in the tree and in every other chart. * [Advanced Node Settings](/advanced-node-settings/): the other node settings, including hide in workspace. * [Chart Types](/chart-types/): the other chart types and tiles. --- # Model Validation URL: https://docs.valsight.ai/model-validation/ Description: Verify that your model's formulas follow correct syntax and are compatible with connected base data. Verify that your model's formulas follow **correct syntax** and are compatible with **connected base data**. ## How it works Model validation examines all nodes in the current model and checks: * Formula syntax is correct * Node references resolve to existing nodes * Connected base data is compatible with the model structure * The model has a baseline * Node references form no cycle, where a node ends up depending on itself * Units are consistent: a node's declared unit matches the one its calculation produces, and every unit used exists in the project * Aggregation settings hold together, for example that a weighted average has a weighting node and that the weighting node carries at least the levels of the node it weights * Formulas inside a `PREVIOUS` loop use only the functions allowed there Units and cycles are the two that modelers meet most often. If issues are found, the validation identifies the specific node(s) and the nature of each error. Model validation does **not** check whether calculation results are logically correct. Use [Validation Nodes](/validation-nodes/) for result-level checks. The validation icon has three possible states: | Symbol | Status | Meaning | | :-----------------------------------------------------------------: | --------------- | -------------------------------------------------------------------------------------------------- | | ![Valid validation icon](./images/validation-valid.svg) | **Valid** | The model, its syntax, and all connected base data are working correctly. | | ![Invalid validation icon](./images/validation-invalid.svg) | **Invalid** | The model or connected base data has issues. Click the icon to see details. | | ![Out-of-date validation icon](./images/validation-out-of-date.svg) | **Out of date** | Changes have been made since the last validation. Only shown when validation is set to **manual**. | Validation can run automatically after each change, or manually on demand. When set to manual, the "out of date" indicator reminds you to re-validate after making changes. ### Errors and warnings Model validation distinguishes **blocking errors** from **non-blocking warnings**. Each validation dialog and node tooltip shows a count per severity, for example "We found 2 errors and 1 warning". On the canvas, the validation indicator on a node is color-coded by severity — **red for errors** and **gold for warnings** — and stays legible whether you are zoomed in or out. A node's indicator reflects the most severe problem among the node's own checks and those of the nodes it feeds into, so an error anywhere downstream escalates the node to an error, even across sub-model boundaries. In the node inspector, a node's problems are grouped into: * **This Node** — problems on the selected node itself. * **Downstream Node Problems** — problems inherited from the nodes it feeds into, each labeled with the model it belongs to when it lives in another sub-model. * **Problems in Other Baselines** — problems that occur only in a baseline other than the active one. ## Steps ### Running a model validation 1. Open your model in the **Model Editor**. 2. Click the **validation icon** in the header bar. ![image-20260402-091325.png](./images/6862700554.png) The validation icon in the header updates to reflect the current state. ### Switching between manual and automatic validation The mode lives in the caret-down menu beside the validation icon, under the heading **Validation Setting**. It offers **Manual** and **Auto**, with a tick against whichever is active. * **Auto** validates the model immediately and keeps it validated after every change. * **Manual** leaves it to you, and the out-of-date icon then tells you when a re-run is due. The same menu holds **Open Validation**, which opens the validation panel without starting a run. ### Showing warnings directly on nodes By default, validation results are only visible in the centralized validation panel. You can optionally display warning icons directly on affected nodes in the canvas, so you can spot issues in context without switching views. 1. Open the **Model** tab in the Context Panel (top-right corner). 2. Activate the **Show Validations** toggle under the **Node Display** section. ![Validation Warnings Displayed Directly on Nodes.png](./images/6862929940.png) This setting is saved per user and project view. Other users control their own visibility independently. ## FAQ **What does model validation check?** Syntax correctness, node reference resolution, and compatibility between formulas and connected base data. **Does model validation check whether results are correct?** No. It checks structure and syntax only. Use Validation Nodes to check result correctness. **What should I do when validation fails?** Click the validation icon to see which nodes have issues. Fix the reported errors and re-validate. If the issue is in your base data, see Data & Dimension Validation. ## Related * [Data & Dimension Validation](/data-dimension-validation/): check uploaded data and dimension compliance * [Validation Nodes](/validation-nodes/): add custom result checks to your model * [Troubleshooting guide](/troubleshooting-guide/): diagnose empty results, wrong shape, and wrong numbers * [Model Editor UI](/model-editor-ui/): full overview of the Model Editor layout --- # Modeling URL: https://docs.valsight.ai/modeling/ Description: Models in Valsight define the underlying calculation logic that connects data, business logic, and drivers as the basis for scenario simulation. **Models** in Valsight define the **underlying calculation logic** that connects data, business logic, and drivers as the basis for scenario simulation. ![image-20260415-194841.png](./images/7009107981.png) ## Start here if you want to: | If you | Go to | | -------------------------------------------------- | ------------------------------------------------ | | Understand how models are built and structured | [Building Models](/building-models/) | | Write or review formulas | [Functions & Formulas](/functions-formulas/) | | Understand the building blocks of the Model Editor | [Model Editor UI](/model-editor-ui/) | | Investigate unexpected formula behavior | [Troubleshooting guide](/troubleshooting-guide/) | ## Who this section is for This section is for users who create, edit, review, or maintain models in Valsight. --- # Modelle URL: https://docs.valsight.ai/modelle/ Description: Diese Seite bietet eine Sammlung von Tutorials und Anleitungen zur Modellierung. Diese Seite bietet eine Sammlung von Tutorials und Anleitungen zur Modellierung. --- # Models URL: https://docs.valsight.ai/models/ Description: Submodels help structure large models by splitting logic into smaller, focused parts. They make complex models easier to understand, maintain, and work on to… Submodels help structure large models by splitting logic into smaller, focused parts. They make complex models easier to understand, maintain, and work on together. In Valsight, submodels are not isolated fragments. They remain fully connected and together form one coherent business model. ## When to use it * When a model becomes large or hard to reason about * When different parts of the logic serve different purposes ## Best practice: the Valsight “fish” structure A recommended way to structure models is the **Valsight fish**, which typically spans **up to six levels**: * **500\_Tail**: Data input models * **400-20X\_Mid-sections**: Market logic, sales volumes, production costs, OPEX * **100\_Head**: P\&L and KPI models Each level represents a clear business responsibility and can be implemented as one or multiple submodels. Submodels can be configured independently, depending on complexity and team needs. This structure improves overview, supports scaling, and makes model logic easier to navigate. ![Valsight\_Fish.PNG](./images/6700335106.png) ## Node availability & model flow Nodes are available for connections based on their position in the fish flow: * Nodes can be used **within their own model** * Nodes can be used in **any model that comes after them** in the flow For example: * Nodes from *Sales* are available in *P\&L* and *KPIs* * Nodes from *KPIs* are **not** available in *Sales* or *P\&L* To support tighter coordination, submodels can also have **two-way relationships** (e.g. *Sales* ↔ *Market Model*). This allows nodes from both models to be used across the connected models. ## Access & permissions Submodels allow **granular access control** across the model structure. Permissions can be set so that a user: * Has access only to specific submodels (e.g. OPEX) * Automatically gains access to all preceding models in the flow * Cannot access other models on the same level or any subsequent models This makes it possible to safely collaborate across teams while protecting sensitive logic. ## FAQ **Do submodels affect results?** No. They only structure logic. **Can I add submodels later?** Yes. Submodels can be added at any time. What matters most is how responsibilities are separated, not how many submodels you create. **Are submodels required?** No. They are most useful for larger or collaborative models. ## Related * [Model Editor UI](/model-editor-ui/) --- # MOM_ABS URL: https://docs.valsight.ai/mom-abs/ Description: Returns the absolute month-over-month growth by calculating the difference between the current and previous month. Missing months can be skipped or treated as zero, depending on the selected behavior. **Category:** [Compare periods](/compare-periods/) ## Overview The **MOM\_ABS** function **returns the absolute growth for each month compared to the previous month** (month-over-month). Use this function when you need the absolute difference between consecutive months. ## Syntax `MOM_ABS('Node' [, "MissingValueBehaviour"])` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ------------------ | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | -- | | **MissingValueBehaviour** | How missing values are treated. | Keyword | No | `"IGNORE_MISSING"` | **MissingValueBehaviour options:** * `"IGNORE_MISSING"`: Missing rows are skipped. This is the default. * `"MISSING_AS_ZERO"`: Missing rows are treated as 0. ## Examples ### Default: ignoring missing values This example shows MOM\_ABS with the default behavior. The missing months are skipped and no result is produced for them. **Input node:** `'Profit'` | Month | Value | | ------- | ----- | | 2025-01 | 200 | | 2025-02 | 300 | | 2025-03 | 450 | | 2025-04 | 500 | | 2026-02 | 100 | **Formula:** `MOM_ABS('Profit')` **Equivalent to:** `MOM_ABS('Profit', "IGNORE_MISSING")` | Month | MOM\_ABS Result | | ------- | --------------- | | 2025-02 | 100 | | 2025-03 | 150 | | 2025-04 | 50 | ### Treating missing values as zero With MISSING\_AS\_ZERO, gaps are filled with 0, producing results for every month including those without input data. **Formula:** `MOM_ABS('Profit', "MISSING_AS_ZERO")` | Month | MOM\_ABS Result | | ------- | --------------- | | 2025-01 | 200 | | 2025-02 | 100 | | 2025-03 | 150 | | 2025-04 | 50 | | 2025-05 | -500 | | 2026-02 | 100 | | 2026-03 | -100 | ## Related | Function | When to use instead | | ------------------------- | ---------------------------------------------------------------------------------------- | | [MOM\_REL](/mom-rel/) | When you need the percentage change month-over-month instead of the absolute difference. | | [YOY\_ABS](/yoy-abs/) | When you need the absolute difference on a yearly basis instead of monthly. | | [DELTA\_ABS](/delta-abs/) | When you need the absolute change along any dimension, not just time. | --- # MOM_REL URL: https://docs.valsight.ai/mom-rel/ Description: Returns the relative month-over-month growth (percentage change) between the current and previous month. Missing months can be skipped or treated as zero, depending on the selected behavior. **Category:** [Compare periods](/compare-periods/) ## Overview The **MOM\_REL** function **returns the relative growth for each month compared to the previous month** (month-over-month). Use this function when you need the percentage change between consecutive months. ## Syntax `MOM_REL('Node' [, "MissingValueBehaviour"])` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ------------------ | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | -- | | **MissingValueBehaviour** | How missing values are treated. | Keyword | No | `"IGNORE_MISSING"` | **MissingValueBehaviour options:** * `"IGNORE_MISSING"`: Missing rows are skipped. This is the default. * `"MISSING_AS_ZERO"`: Missing rows are treated as 0. ## Examples ### Default: ignoring missing values This example shows MOM\_REL with the default behavior. The missing months are skipped and no result is produced for them. **Input node:** `'Profit'` | Month | Value | | ------- | ----- | | 2025-01 | 200 | | 2025-02 | 300 | | 2025-03 | 450 | | 2025-04 | 500 | | 2026-02 | 100 | **Formula:** `MOM_REL('Profit')` **Equivalent to:** `MOM_REL('Profit', "IGNORE_MISSING")` | Month | Calculation | Result | | ------- | ----------------- | ------ | | 2025-02 | (300 - 200) / 200 | 0.5 | | 2025-03 | 150 / 300 | 0.5 | | 2025-04 | 50 / 450 | 0.11 | ### Treating missing values as zero With MISSING\_AS\_ZERO, gaps are filled with 0, producing results for every month including those without input data. **Formula:** `MOM_REL('Profit', "MISSING_AS_ZERO")` | Month | Calculation | Result | | ------- | ----------------- | ------ | | 2025-02 | (300 - 200) / 200 | 0.5 | | 2025-03 | 150 / 300 | 0.5 | | 2025-04 | 50 / 450 | 0.11 | | 2025-05 | (0 - 500) / 500 | -1 | | 2026-03 | (0 - 100) / 100 | -1 | 2026-02 is not present in the result: even with MISSING\_AS\_ZERO, dividing by a zero previous value causes a division by zero, so the entry is dropped. ## Related | Function | When to use instead | | ------------------------- | ------------------------------------------------------------------------------- | | [MOM\_ABS](/mom-abs/) | When you need the absolute difference month-over-month instead of a percentage. | | [YOY\_REL](/yoy-rel/) | When you need the percentage change on a yearly basis instead of monthly. | | [DELTA\_REL](/delta-rel/) | When you need relative change along any dimension, not just time. | --- # MOVINGAVG URL: https://docs.valsight.ai/movingavg/ Description: The MOVINGAVG function returns the moving average over the last WindowSize elements including the current one, returning null for entries where the window cannot be fully filled. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **MOVINGAVG** function **returns the moving average over the last WindowSize elements including the current one**. If there are not enough preceding elements to fill the window, null is returned for those entries. Use this function when you need a rolling average over a defined time window. ## Syntax `MOVINGAVG('Node', "TimeLevel", WindowSize)` **Example usage:** `MOVINGAVG('Revenue', "Month", 3)` ## Parameters | Parameter | Description | Type | Required | | -------------- | ----------------------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | | **TimeLevel** | Name of the time level that forms the time series to average (e.g.`"Month"`, `"Quarter"`) | Level name | Yes | | **WindowSize** | Number of elements (including the current one) to average. Must be greater than 0. | Number | Yes | ## Output shape | Aspect | Behavior | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as input, but the time dimension is at the specified TimeLevel granularity. If the input is finer than the specified level, it is automatically rolled up. | | Time range | The first (WindowSize - 1) entries are dropped because there are not enough preceding values to fill the window. | | Values | Each value is the average of the current and the preceding (WindowSize - 1) entries along the time level. | | Row count | Reduced by at least (WindowSize - 1) entries compared to the input, and by more if the series has gaps. | ## Watch out * The first **(WindowSize - 1) entries** are always null (dropped) because the window cannot be fully filled. * A **gap in the middle** of the series costs more than the one period. The window has to hold WindowSize values, so a single missing period also blanks the following (WindowSize - 1) periods. On a series with holes the result therefore loses more rows than the leading (WindowSize - 1). * The input must have a **time level**. If the input has no time dimension, the function fails. * The input must be **at least as fine-grained** as the specified time level. For example, you cannot compute a moving average on `"Month"` if the input only has `"Year"` data. * If the input is finer than the specified level (e.g. input is at `"Month"` but you specify `"Quarter"`), the data is automatically rolled up to the specified level before averaging. ## Examples ### Two-period moving average by quarter This example shows a two-period moving average across quarterly values. The result starts once enough values are available to fill the window. **Input node:** `'Profit'` | Quarter | Profit | | ------- | ------ | | 2025-Q1 | 30 | | 2025-Q2 | 120 | | 2025-Q3 | 210 | | 2025-Q4 | 300 | **Formula:** `MOVINGAVG('Profit', "Quarter", 2)` | Quarter | Calculation | Result | | ------- | --------------- | ------ | | 2025-Q2 | (30 + 120) / 2 | 75 | | 2025-Q3 | (120 + 210) / 2 | 165 | | 2025-Q4 | (210 + 300) / 2 | 255 | 2025-Q1 has no result because there is no preceding quarter to complete the two-element window. ### Three-period moving average with additional dimensions MOVINGAVG computes the window independently for each combination of non-time dimensions. **Input node:** `'Sales'` | Month | Region | Value | | ------- | ------ | ----- | | 2025-01 | EMEA | 100 | | 2025-02 | EMEA | 200 | | 2025-03 | EMEA | 150 | | 2025-01 | APAC | 50 | | 2025-02 | APAC | 80 | | 2025-03 | APAC | 110 | **Formula:** `MOVINGAVG('Sales', "Month", 3)` | Month | Region | Calculation | Result | | ------- | ------ | --------------------- | ------ | | 2025-03 | EMEA | (100 + 200 + 150) / 3 | 150 | | 2025-03 | APAC | (50 + 80 + 110) / 3 | 80 | With a window of 3, only the third month has enough preceding values. Each region is averaged independently. ## Related | Function | When to use instead | | ------------------------ | -------------------------------------------------------------------------------------------------- | | [MOVINGSUM](/movingsum/) | When you need a rolling sum over the same time window instead of an average. | | [SHIFT](/shift/) | When you need to shift values along a time level rather than aggregate them over a rolling window. | --- # MOVINGSUM URL: https://docs.valsight.ai/movingsum/ Description: The MOVINGSUM function returns the moving sum over the last WindowSize elements including the current one, returning null for entries where the window cannot be fully filled. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **MOVINGSUM** function **returns the moving sum over the last WindowSize elements including the current one**. If there are not enough preceding elements to fill the window, null is returned for those entries. Use this function when you need a rolling sum over a defined time window. ## Syntax `MOVINGSUM('Node', "TimeLevel", WindowSize)` **Example usage:** `MOVINGSUM('Revenue', "Month", 12)` ## Parameters | Parameter | Description | Type | Required | | -------------- | ---------------------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | | **TimeLevel** | Name of the time level that forms the time series to sum up (e.g.`"Month"`, `"Quarter"`) | Level name | Yes | | **WindowSize** | Number of elements (including the current one) to sum up. Must be greater than 0. | Number | Yes | ## Output shape | Aspect | Behavior | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as input, but the time dimension is at the specified TimeLevel granularity. If the input is finer than the specified level, it is automatically rolled up. | | Time range | The first (WindowSize - 1) entries are dropped because there are not enough preceding values to fill the window. | | Values | Each value is the sum of the current and the preceding (WindowSize - 1) entries along the time level. | | Row count | Reduced by at least (WindowSize - 1) entries compared to the input, and by more if the series has gaps. | ## Watch out * The first **(WindowSize - 1) entries** are always null (dropped) because the window cannot be fully filled. * A **gap in the middle** of the series costs more than the one period. The window has to hold WindowSize values, so a single missing period also blanks the following (WindowSize - 1) periods. On a series with holes the result therefore loses more rows than the leading (WindowSize - 1). * The input must have a **time level**. If the input has no time dimension, the function fails. * The input must be **at least as fine-grained** as the specified time level. For example, you cannot compute a moving sum on `"Month"` if the input only has `"Year"` data. * If the input is finer than the specified level (e.g. input is at `"Month"` but you specify `"Quarter"`), the data is automatically rolled up to the specified level before summing. ## Examples ### Two-period moving sum by quarter This example shows a two-period moving sum across quarterly values. The result starts once enough values are available to fill the window. **Input node:** `'Profit'` | Quarter | Profit | | ------- | ------ | | 2025-Q1 | 30 | | 2025-Q2 | 120 | | 2025-Q3 | 210 | | 2025-Q4 | 300 | **Formula:** `MOVINGSUM('Profit', "Quarter", 2)` | Quarter | Calculation | Result | | ------- | ----------- | ------ | | 2025-Q2 | (30 + 120) | 150 | | 2025-Q3 | (120 + 210) | 330 | | 2025-Q4 | (210 + 300) | 510 | 2025-Q1 has no result because there is no preceding quarter to complete the two-element window. ### Four-quarter rolling sum (trailing twelve months) A common use case: summing the last 4 quarters to get a trailing twelve-month total. **Input node:** `'Revenue'` | Quarter | Value | | ------- | ----- | | 2025-Q1 | 100 | | 2025-Q2 | 120 | | 2025-Q3 | 90 | | 2025-Q4 | 140 | | 2026-Q1 | 110 | | 2026-Q2 | 130 | **Formula:** `MOVINGSUM('Revenue', "Quarter", 4)` | Quarter | Calculation | Result | | ------- | -------------------- | ------ | | 2025-Q4 | 100 + 120 + 90 + 140 | 450 | | 2026-Q1 | 120 + 90 + 140 + 110 | 460 | | 2026-Q2 | 90 + 140 + 110 + 130 | 470 | The first three quarters have no result because the four-element window cannot be filled. ## Related | Function | When to use instead | | -------------------------- | -------------------------------------------------------------------------------------------------- | | [MOVINGAVG](/movingavg/) | When you need a rolling average over the same time window instead of a sum. | | [SHIFT](/shift/) | When you need to shift values along a time level rather than aggregate them over a rolling window. | | [RUNNINGSUM](/runningsum/) | When you need a cumulative sum from the start of the time series (no fixed window). | --- # Multidimensional Data Upload (2D/3D/4D Tables) URL: https://docs.valsight.ai/multidimensional-data-upload-2d-3d-4d-tables/ Description: If your source systems present data in some sort of formatted table rather than a structured "database like" table you can use the 2D and 3D upload functiona… Upload multidimensional data by declaring the dimension levels and the measure name in cell A1, which turns a formatted 2D, 3D or 4D table into structured data. ## Create a 2D/3D data table If your source systems present data in some sort of formatted table rather than a structured "database like" table you can use the 2D and 3D upload functionality. The identifier in Cell A1 has to contain the following information: ### 3D / LevelName1 / LevelName2 / LevelName3 / MeasureName | Fragment | Explanation | | ----------- | -------------------------------------------------------------------------------------------------------------------------------- | | 3D | The identifier tells Valsight that this table should be considered a 3D table | | LevelName1 | The Name of the level that the data in column A belongs to. Should match a level name exactly. | | LevelName2 | The Name of the level that the data in column B belongs to. Should match a level name exactly. | | LevelName3 | The Name of the level that the data in Row 1, starting at Cell B1 (2D) or C1 (3D) belongs to. Should match a level name exactly. | | MeasureName | The data will be available as this column in the resulting Valsight Table. | The identifier is not capped at 4D. Any whole number followed by `D` is accepted, with one level name per fragment and the measure name last, so wider tables work the same way. You can also use the =DIM\[Dim,Level,#] identifier for each level name to create a Dimension "on the fly". However, for best results and a structured approach, you should rather have these information in separate Dimension tables. Download an example 2D / 3D / 4D upload sheet at [Example Excel Sheets](/example-excel-sheets/). To illustrate the way a 3D upload works: the following two tables are equivalent: | 3D / ExampleProduct / ExampleChannel / Year / Volume | ExampleChannel | 2018 | 2019 | | ---------------------------------------------------- | -------------- | ---- | ---- | | Product A | Online | 10 | 40 | | Product B | Offline | 20 | 30 | Equivalent regular upload table: | Year | ExampleProduct | ExampleChannel | Volume | | ---- | -------------- | -------------- | ------ | | 2018 | Product A | Online | 10 | | 2018 | Product B | Offline | 20 | | 2019 | Product A | Online | 40 | | 2019 | Product B | Offline | 30 | --- # MULTIPLICATION (*) URL: https://docs.valsight.ai/multiplication/ Description: The MULTIPLICATION operator multiplies two inputs across their combined dimension set. In other words, multiplication uses the union of both inputs’ dimensions. **Category:** [Arithmetic operators](/arithmetic-operators/) ## Overview The **MULTIPLICATION** operator **multiplies two inputs** across their **combined dimension set**. In other words, multiplication uses the **union** of both inputs’ dimensions. The result keeps the **finer** level in each shared dimension and retains dimensions that exist on only one side. Use this operator for standard multiplication without additional validation handling. ## Syntax `'Node1' * 'Node2'` **Example usage:** `'Volume' * 'Price'` ## Parameters | Parameter | Description | Type | Required | | --------- | ---------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First factor node, specified using the node name in single quotes (e.g.`'Volume'`) | Node reference | Yes | | **Node2** | Second factor node, specified using the node name in single quotes (e.g.`'Price'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | The result uses the **combined dimension set** (the **union** of both inputs’ dimensions). Per shared dimension, the **finer** level is used. Dimensions that exist on only one side are kept as-is. | | Level values | Values are matched on shared dimensions. Non-shared dimensions expand the result across matching rows. | | Row count | Equal or expanded. A cell where exactly one factor is missing becomes `0`; only cells where **both** factors are missing are `N/A`. | ## Watch out * Multiplication uses the **combined dimension set** (**union**), not the common dimensions. This is the opposite of addition and subtraction. * If one input has additional dimensions, the result expands to keep them. * This expansion is a common cause of unexpected output shape. * **The expansion fills with zeros, not blanks.** Where exactly one factor is missing the product is a defined `0`, and the result is `N/A` only where both factors are missing. `'Volume' * 'Price'` produces a real 0 at every intersection where Price exists but Volume does not, and those zeros then sum into totals rather than being skipped. This is what makes the expansion above dangerous. * Units are multiplied together as well. For example, `EUR` \* `Quantity` produces the combined unit `EUR * Quantity`. ## Examples ### Multiplying nodes with matching dimensions **Input node:** `'Node1'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 4 | **Input node:** `'Node2'` | Year | Value | | ---- | ----- | | 2025 | 3 | | 2026 | 1 | **Formula:** `'Node1' * 'Node2'` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 2 × 3 | 6 | | 2026 | 4 × 1 | 4 | ### Multiplying nodes with some shared dimensions This example shows how multiplication keeps the finer dimensionality from `Node2`. **Input node:** `'Node1'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 4 | **Input node:** `'Node2'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | A | 2 | | 2025 | B | 0 | | 2026 | A | 1 | | 2026 | B | 4 | **Formula:** `'Node1' * 'Node2'` | Year | Product | Calculation | Result | | ---- | ------- | ----------- | ------ | | 2025 | A | 2 × 2 | 4 | | 2025 | B | 2 × 0 | 0 | | 2026 | A | 4 × 1 | 4 | | 2026 | B | 4 × 4 | 16 | ### Multiplying by a scalar When one input is a scalar value, that value is applied across all rows of the other input. **Input node:** `'Node1'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 4 | **Input node:** `'Node2'` | Value | | ----- | | 2 | **Formula:** `'Node1' * 'Node2'` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 2 × 2 | 4 | | 2026 | 4 × 2 | 8 | ## Related | Function | When to use instead | | -------------------------- | -------------------------------------------------------------------------------------------- | | [MULTIPLY](/multiply/) | When you want multiplication with explicit validation options and clearer mismatch handling. | | [DIVISION (/)](/division/) | When you want the same combined-dimension logic but need to divide instead of multiply. | --- # MULTIPLY URL: https://docs.valsight.ai/multiply/ Description: The MULTIPLY function extends the * operator with optional validation for missing rows. It produces the same result as 'Node1' * 'Node2' when validation passes. When validation fails, it produces an error with a detailed explanation of which rows are missing. **Category:** [Math & numeric](/math-numeric/) ## Overview The **MULTIPLY** function **extends the** `*` **operator with optional validation for missing rows**. It produces the same result as `'Node1' * 'Node2'` when validation passes. When validation fails, it produces an error with a detailed explanation of which rows are missing. Use this function when you want standard multiplication but need to detect mismatches between the two input nodes. ## Syntax `MULTIPLY('Node1', 'Node2' [, "Validation"])` **Example usage:** `MULTIPLY('Volume', 'Price', "FailOnMissing")` ## Parameters | Parameter | Description | Type | Required | Default | | -------------- | ---------------------------------------------------------------------------------- | -------------- | -------- | ---------------- | | **Node1** | First factor node, specified using the node name in single quotes (e.g.`'Volume'`) | Node reference | Yes | -- | | **Node2** | Second factor node, specified using the node name in single quotes (e.g.`'Price'`) | Node reference | Yes | -- | | **Validation** | Controls how mismatches between the two input nodes are handled. | Keyword | No | `"NoValidation"` | **Validation options:** * `"NoValidation"`: No mismatch check. Behaves exactly as the `*` operator. This is the default. * `"FailOnMissingFirst"`: Fails if any row in Node1 has no matching row in Node2. * `"FailOnMissingSecond"`: Fails if any row in Node2 has no matching row in Node1. * `"FailOnMissing"`: Fails if either node has rows not matched by the other (combines both checks). ## Output shape | Aspect | Behavior | | -------------- | --------------------------------------------------------------------------------------------------------------- | | Dimensionality | **Union** of all dimensions from both inputs (same as `*`). Per shared dimension, the **finest** level is used. | | Level values | Matched on shared dimensions. Non-shared dimensions are applied across all matching rows. | | Row count | Equal or expanded. Where one input has no matching value, the result is **0** (not N/A). | ## Watch out * Using validation has a **performance impact**. Only use it when you need to detect mismatches. * Without validation (or with `NoValidation`), MULTIPLY is identical to `*`. Where one input has no matching value for a row, the result is **0**. ## Examples ### Validation behavior This example shows the default multiplication result and how the different validation modes behave when the two input nodes do not fully overlap. The missing years at the start and end of the time range trigger the validation errors. **Input node:** `'Node1'` | Year | Value | | ---- | ----- | | 2026 | 6 | | 2027 | 4 | | 2028 | 10 | **Input node:** `'Node2'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 3 | | 2027 | 1 | **Formula:** `MULTIPLY('Node1', 'Node2')` **Equivalent to:** `MULTIPLY('Node1', 'Node2', "NoValidation")` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | N/A × 2 | 0 | | 2026 | 6 × 3 | 18 | | 2027 | 4 × 1 | 4 | | 2028 | 10 × N/A | 0 | **Formula:** `MULTIPLY('Node1', 'Node2', "FailOnMissingFirst")` **Error:** The calculation fails because year 2028 from `Node1` has no matching value in `Node2`. **Formula:** `MULTIPLY('Node1', 'Node2', "FailOnMissing")` **Error:** The calculation fails because year 2028 from `Node1` has no matching value in `Node2` and year 2025 from `Node2` has no matching value in `Node1`. **Formula:** `MULTIPLY('Node1', 'Node2', "FailOnMissingSecond")` **Error:** The calculation fails because year 2025 from `Node2` has no matching value in `Node1`. ## Related | Function | When to use instead | | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | | [MULTIPLICATION (\*)](/multiplication/) | When you want standard multiplication across shared levels without additional validation handling. | | [DIVIDE](/divide/) | When you need the same kind of validated arithmetic behavior but want to divide values instead of multiplying them. | --- # Naming Guidelines URL: https://docs.valsight.ai/naming-guidelines/ Description: Object Guideline Notes Good Example Bad Example | Object | Guideline | Notes | Good Example | Bad Example | | ------------------ | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | -------------------- | | Data Sources | A-Z a-z \_, , Numbers | Must be usable from DATA() functions. Avoid putting version information in the name and use the description instead. | SALES\_DATA\_PRODUCTION, "GEM Data" | | | Dimension & Levels | A-Z a-z \_ | Since level names are automatically matched, the levels should adhere to the same rules as Excel Column names. | Location, Product\_D, PRODUCT\_D, PRODUCT, PRODUCT\_CODE | Product-Code, 123Dim | | Excel Worksheets | Recommended: A-Z, a-z, \_ Append \_DIM for Dimension Sheets | Not enforced. Spaces, numbers and other characters are accepted, and a name with spaces works in DATA() as long as it is quoted exactly. Sticking to letters and underscores keeps formulas short and avoids surprises when a name is reused elsewhere. | Sales, FTEs, Price and Volume | 2018-03 | | Excel Column Names | Recommended: A-Z, a-z, \_ | Not enforced, the same as worksheet names. Column names are quoted in DATA() too. | Volume, Number\_of\_Units\_Sold | | | Excel Filename | The filename has no implications for Valsight, as the Data Source name is used to access the file. | | | | --- # NEQ (!=) URL: https://docs.valsight.ai/neq/ Description: Checking whether matching rows are different **Category:** [Logical functions](/logical-functions/) ## Overview The **NEQ** function **compares the rows of two inputs** and returns true (1) if the values are not equal and false (0) otherwise. Use this function when you need a 1/0 flag to mark mismatching values between two inputs. ## Syntax `NEQ('Node1', 'Node2')` `'Node1' != 'Node2'` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | | **Node2** | Second input node. | Node reference | Yes | ## Watch out * A row that exists in only **one** of the two inputs is still compared. The missing side counts as 0, so the row comes back as `1` unless the value that is there is also 0. Nothing is dropped. * Because of that, a gap and a genuine mismatch look identical in the result. If you use NEQ to reconcile two nodes, check first that both cover the same rows, for example with [FINDMISSING](/findmissing/). ## Examples ### Checking whether matching rows are different This example compares two input nodes row by row. The result returns 1 where the values differ and 0 where they are equal. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 400 | | 2026 | 700 | | 2027 | 850 | | 2028 | 500 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 350 | | 2026 | 400 | | 2027 | 850 | | 2028 | 600 | **Formula:** `NEQ('A', 'B')` | Year | NEQ Result | | ---- | ---------- | | 2025 | 1 | | 2026 | 1 | | 2027 | 0 | | 2028 | 1 | ## Related | Function | When to use instead | | -------------- | -------------------------------------------------------------------------------------------------- | | [EQ (=)](/eq/) | When you want to mark matching values instead of mismatches between two inputs. | | [GT (>)](/gt/) | When you need to check whether one input is greater than another instead of checking for equality. | | [LT (<)](/lt/) | When you need to check whether one input is less than another instead of checking for inequality. | --- # Node Actions URL: https://docs.valsight.ai/node-actions/ Description: Nodes can be changed individually or in batches Nodes can be changed individually or in batches. * Select a single Node by clicking on it. * Use 'Tree select' to select all Nodes that are required for the calculation of the current Node. * Hold CTRL (**⌘** on Mac) and click to select multiple Nodes. * Hold CTRL (**⌘** on Mac) and click on selected Nodes to deselect them. ![image2020-4-29\_13-53-18.png](./images/5094194658.png) ## Copy and paste Nodes can be copied by selecting the three-dot action menu in the Node Editor header and 'Copy', or by pressing Ctrl+C (**⌘**+C on Mac) on the keyboard. The copied Nodes can then be pasted with Ctrl+V (**⌘**+V on Mac). Nodes can be pasted in the same Model, other Models of the same or different projects, and also into another instance. On paste, Nodes might become invalid as references to not accessible elements are removed. This can include references in the operation like other Nodes or data sources as well as setting like the weighting Node for a weighted average aggregation or impact proxies. ![Screenshot 2020-04-29 at 14.00.42.png](./images/5094194653.png) ## Move to other models If you want to move Nodes to another Model, select the three-dot action menu and 'Move'. This will keep references to assumption line items intact. The move operation might fail if references would be invalid due to the move. If the move succeeds, the Node(s) are still valid and numbers do not change. ![image-20220224-154252.png](./images/5094230840.png) ## Deletion Delete Nodes with the red trash button in the Node Editor header, to the left of the three-dot action menu. That menu itself holds only 'Move' and 'Copy'. Deletion can be refused. A node that is still referenced elsewhere is kept, and the product reports "Cannot delete nodes" with the list "These nodes are in use by other nodes or line-items:" and the hint "Remove references, then try again." Use 'Show references' in that dialog to see what is holding the node. A node is in use when another node's operation refers to it, or when an assumption line-item is defined on it, so clear those first and delete again. ![Screenshot 2020-04-29 at 14.02.02.png](./images/5094194663.png) ## Search Click the search icon in the action bar at the bottom of the canvas, in the 'Navigate' group next to the zoom controls, or hit CTRL + F (**⌘** + F on Mac) to search for Nodes in your current Model and Submodels. ![search.gif](./images/5094193124.gif) --- # Node Editor URL: https://docs.valsight.ai/node-editor/ Description: The Node Editor is the right-hand panel in the Model Editor where individual nodes are configured. It controls how a node behaves, how its values are display… The Node Editor is the right-hand panel in the Model Editor where individual nodes are configured. It controls how a node behaves, how its values are displayed and aggregated, and whether it is accessible to users in simulation workspaces. This section covers the settings and actions available in the Node Editor, from basic display options to simulation and export configuration. ## What you'll find in this section | If you | Go to | | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | Want to select, copy, move, delete, or search for nodes in a model | [Node Actions](/node-actions/) | | Want to assign display labels such as `EUR` or `km` to node values | [Units](/units/) | | Need to control how node values are summarized across dimensions | [Aggregation Settings](/aggregation-settings/) | | Want to configure connector visibility, node coloring, or export inclusion | [Advanced Node Settings](/advanced-node-settings/) | | Want to mark nodes as editable in simulation workspaces | [Allow Simulation of Nodes](/allow-simulation-of-nodes/) | | Want a node to carry only one assumption per scenario | [Workspace Validation](/workspace-validation/) | | Want to check a node's shape or have it flag bad results | [Expected Levels](/expected-levels/), [Validation Nodes](/validation-nodes/) | ## Who this section is for This section is relevant for model builders who are building or maintaining models in the Model Editor. It becomes relevant as soon as a model moves beyond initial setup and nodes need to be fine-tuned for presentation, calculation accuracy, or simulation use. ## How this section fits into Valsight The Node Editor works alongside the Model Editor canvas and the Formula Editor. Once nodes are configured here, their behavior is reflected across simulation workspaces, charts, and exports throughout the application. --- # Node Usage URL: https://docs.valsight.ai/node-usage/ Description: The Usage tab in the node inspector shows everywhere a node is used across models, shared scenarios, and workspaces. The **Usage** tab in the node inspector shows everywhere a node is used, so you can see what depends on it before you change or delete it. ## What the Usage tab shows Select a single node in the model editor and open the **Usage** tab in the inspector. The tab groups where the node is used into three sections, each with a total count: * **Models** — other nodes that reference this node in a formula or as a weight. * **Shared Scenarios** — shared scenario runs that use the node. * **Workspaces** — charts, line-items, and versions that use the node. Each entry lists its **Name** and the number of **Uses**. Use the **Refresh** button to rebuild the report for the current state of the project. ## The full usage report Select **View Full Usage** to open the **Node Usage** report — a full table of every reference, with columns for **Model**, **Referencing Node**, **Assumption Group / Sheet**, **Line-Item Name**, and **Used as**. The **Used as** column tells you how the node is used in each place: * **Formula** — referenced in another node's formula. * **Weight** — used as a weighting on another node. * **Line-Item** — read by a line-item. * **Chart** — plotted in a chart. * **Version** — captured in a saved version. In the report you can search for a specific entry, **Expand All** or **Collapse All** the sections, and turn on **Only deletion blockers** to narrow the list to the usages that stop the node from being deleted. ## Deletion blockers Some usages prevent a node from being deleted and some do not. Formula and weighting references block deletion; usages such as charts and line-items are listed for reference but do not block it. The **Only deletion blockers** filter shows exactly which references you need to resolve first. When a section has usages but none of them block deletion, the report says **No Usages Prevent Deletion**. ## Good to know * **Single node only:** the report describes one node at a time. Select a single node to see its usage. * **Refresh for the latest:** a report can be marked **Potentially Outdated** after changes; select **Refresh** to rebuild it. * **Access is respected:** usages you do not have the rights to see are shown as a restricted count rather than listed, and a node whose usage you cannot view at all shows **No Access**. ## Related * [Node actions](/node-actions/): renaming, moving, and deleting nodes. * [Model Validation](/model-validation/): check that node formulas and references resolve. The node usage report groups references into `models`, `lineItems`, `charts`, `versions`, and `sharedScenarios`. Each referencing node carries `referenceKinds` (`formula` | `weighting`) and a separate `preventsDeletion` flag — a reference can be reported without blocking deletion (charts and line-items never block; formula and weighting references do). Usages the caller cannot access are returned as counts in `restrictedCounts`, not as entries. --- # Nodes URL: https://docs.valsight.ai/nodes/ Description: Nodes are the fundamental building blocks of a model. Each node represents a value or calculation, and together they form a dependency graph that defines how… Nodes are the fundamental building blocks of a model. Each node represents a value or calculation, and together they form a dependency graph that defines how results are produced. ## The role of nodes in Valsight * Express business logic in a structured and transparent way * Represent values and calculations in a multidimensional way * Define which values are editable, simulated, or data-driven * Ensure models remain inspectable and evolvable as they grow ## How they work A model is composed of individual nodes, each representing a single value or calculation. Nodes reference other nodes as inputs, forming a directed graph of dependencies that determines calculation order and results. Each node: * Exists as a separate, selectable element * Encapsulates one logical step (input, calculation, aggregation, or check) * Can be reused by other nodes through references Nodes do not execute in isolation: their value is always determined by the nodes they depend on and the logic defined within them. The dependency graph has to be **acyclic**. A node cannot depend, directly or through a chain of other nodes, on its own result. Model validation rejects a cycle with "The Model contains a cyclic reference between these nodes:" followed by the nodes involved, and marks each one "Node is part of a cyclic reference". Break the loop by introducing a node that holds the prior value, for example with [SHIFT](/shift/) or a roll-forward, so the chain moves forward in time instead of closing on itself. There are four node types, each serving a distinct purpose: * **Standard nodes** Used for step-by-step construction of calculation logic. * **Simulation nodes** Mark assumptions or measures that can be adjusted in simulation workspaces. * **Data nodes** Serve as entry points for external data. * **Validation nodes** Check results against defined rules and flag deviations. ![Node dependencies.png](./images/6648954884.png) ## Using the feature * You can create nodes to represent inputs, calculations, aggregations, or checks. * You can select and edit nodes individually or in groups to evolve model logic. * You can mark specific nodes as simulation-enabled to allow controlled changes in simulations. * You can reuse nodes by copying and pasting them within or across models and projects. Advanced usage typically involves combining different node types to clearly separate inputs, logic, validation, and simulation control. ## Limitations * Nodes only define logic; they do not store historical results or scenario outcomes. * Visual proximity does not imply dependency; only explicit references create relationships. * Grouping or coloring nodes is purely visual and does not affect calculations. * Simulation behavior applies only to nodes explicitly marked as simulation-enabled. ## FAQ **What does a node represent?** A single value or calculation step within a model. **Can one node be used in multiple calculations?** Yes. Nodes can be referenced by multiple other nodes. **Do nodes execute in a specific order?** Execution order is determined automatically by dependencies between nodes. **Does changing a node affect all results?** Yes. Any node that depends on it will be recalculated. ## Related * [Model Editor UI](/model-editor-ui/) --- # NONSIM URL: https://docs.valsight.ai/nonsim/ Description: The NONSIM function returns the value of a node with no assumptions applied to that node. Upstream nodes that affect the input still have their assumptions applied. **Category:** [Assumptions & result sets](/assumptions-result-sets/) ## Overview The **NONSIM** function **returns the value of a node with no assumptions applied to that node**. Upstream nodes that affect the input still have their assumptions applied. Use this function when you want to isolate the effect of assumptions placed on the node itself, while keeping upstream assumptions active. ## Syntax `NONSIM('Node' [, "useVariablesFrom"])` **Example usage:** `NONSIM('Revenue')` ## Parameters | Parameter | Description | Type | Required | Default | | -------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ------------ | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | -- | | **useVariablesFrom** | Determines which variable values are used in the calculation | Keyword | No | `"SCENARIO"` | **useVariablesFrom options:** * `"SCENARIO"`: Uses variable values as overridden by the scenario. This is the default. * `"PROJECT"`: Uses the original project default values instead of scenario overrides. ## Output shape | Aspect | Behavior | | -------------- | ---------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as the input node. | | Values | The input node's values computed without its own assumptions, but with upstream assumptions still applied. | | Row count | Same as the input node's values without its own assumptions. | ## Watch out * The input must be a **single node reference**. Combinations of operations (e.g. `'A' + 'B'`) are not valid. * NONSIM only removes assumptions from the **specified node**. Upstream nodes keep their assumptions. To remove assumptions from the node and all upstream nodes, use [BASELINE](/baseline/) instead. * If the model has **multiple baselines**, the baseline of the current scenario is used. * The **PROJECT** mode only applies project default variable values to nodes calculated within the NONSIM function. Upstream nodes outside the NONSIM call still use scenario variable values. ## Examples ### Baseline values without assumptions This example shows the baseline result of multiplying two nodes when no assumptions or variable overrides are applied. The project default variable $MY\_VAR is set to 10. **Project default variables:** $MY\_VAR = 10 **Input node:** `'Node 1'` | Year | Value | | ---- | ------------- | | 2025 | $MY\_VAR = 10 | | 2026 | $MY\_VAR = 10 | | 2027 | $MY\_VAR = 10 | | 2028 | $MY\_VAR = 10 | **Input node:** `'Node 2'` | Year | Value | | ---- | ----- | | 2025 | 1 | | 2026 | 1 | | 2027 | 1 | | 2028 | 1 | **Formula:** `'Node 1' * 'Node 2'` | Year | Value | | ---- | ----- | | 2025 | 10 | | 2026 | 10 | | 2027 | 10 | | 2028 | 10 | These are the baseline results with no assumptions applied. ### Values with scenario overrides and assumptions This example shows how the same nodes look when a scenario overrides $MY\_VAR to 20 and assumptions are activated on both nodes. **Variable override via scenario:** $MY\_VAR = 20 **Input node:** `'Node 1'` (with overridden $MY\_VAR as 'Base' and activated assumptions as 'Change') | Year | Base | Change | Result | | ---- | ---- | ------ | ------ | | 2025 | 20 | 0 | 20 | | 2026 | 20 | 10 | 30 | | 2027 | 20 | 20 | 40 | | 2028 | 20 | 30 | 50 | **Input node:** `'Node 2'` (with the initial measures as 'Base' and activated assumptions as 'Change') | Year | Base | Change | Result | | ---- | ---- | ------ | ------ | | 2025 | 1 | 1 | 2 | | 2026 | 1 | 2 | 3 | | 2027 | 1 | 3 | 4 | | 2028 | 1 | 4 | 5 | **Formula:** `'Node 1' * 'Node 2'` **Result node:** (with its own activated assumption adding +5 as 'Change') | Year | Base (Node 1 × Node 2) | Change | Result | | ---- | ---------------------- | ------ | ------ | | 2025 | 20 × 2 | 5 | 45 | | 2026 | 30 × 3 | 5 | 95 | | 2027 | 40 × 4 | 5 | 165 | | 2028 | 50 × 5 | 5 | 255 | ### Comparing SCENARIO vs PROJECT mode This example shows the difference between the two modes. NONSIM removes only the Result Node's own assumptions (+5 Change) but keeps upstream assumptions on Node 1 and Node 2. **Formula:** `NONSIM('Result Node')` **Equivalent to:** `NONSIM('Result Node', "SCENARIO")` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 20 × 2 | 40 | | 2026 | 30 × 3 | 90 | | 2027 | 40 × 4 | 160 | | 2028 | 50 × 5 | 250 | The Result Node's own assumption (+5) is removed, but Node 1 and Node 2 keep their assumptions and the scenario's variable override ($MY\_VAR = 20). **Formula:** `NONSIM('Result Node', "PROJECT")` | Year | Calculation | Result | | ---- | ------------- | ------ | | 2025 | 10 × 2 | 20 | | 2026 | (10 + 10) × 3 | 60 | | 2027 | (10 + 20) × 4 | 120 | | 2028 | (10 + 30) × 5 | 200 | PROJECT mode reverts $MY\_VAR to the project default (10), so Node 1's base becomes 10 instead of 20. Node 1's upstream assumptions (Change = 0, 10, 20, 30) and Node 2's assumptions are still applied. ## Related | Function | When to use instead | | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | [BASELINE](/baseline/) | When you want to remove assumptions from the node and all upstream nodes. NONSIM only removes assumptions from the specified node itself. | --- # NOT URL: https://docs.valsight.ai/not/ Description: Inverts the input values with the logical NOT operation. If the input is true (non-zero), false (0) is returned, and true (1) otherwise. Use when you want to invert an existing logical condition so true becomes false and false becomes true. **Category:** [Logical functions](/logical-functions/) ## Overview The **NOT** function **inverts the input values with the logical NOT operation**. If the input is true (non-zero), false (0) is returned, and true (1) otherwise. Use this function when you want to invert an existing logical condition so true becomes false and false becomes true. ## Syntax `NOT('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | ## Examples ### Typical use This example shows that `NOT` turns non-zero values into 0 and turns 0 into 1. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 400 | | 2026 | 0 | | 2027 | 850 | | 2028 | 500 | **Formula:** `NOT('A')` | Year | NOT Result | | ---- | ---------- | | 2025 | 0 | | 2026 | 1 | | 2027 | 0 | | 2028 | 0 | ## Related | Function | When to use instead | | ----------------- | ---------------------------------------------------------------------------------------- | | [TRUE](/true/) | When you need a constant true condition instead of inverting an existing logical result. | | [IS\_NA](/is-na/) | When you want to detect undefined values instead of inverting true and false results. | --- # NPER URL: https://docs.valsight.ai/nper/ Description: Calculates the number of periods needed for a recurring investment, given an interest rate, periodic payment, and present value. **Category:** [Finance functions](/finance-functions/) ## Overview The **NPER** function **calculates the number of periods necessary for a recurring investment** based on an interest rate, the amount of payment per period, a present value, a future value, and either ordinary annuity or annuity due (`Type`) indicating whether payments are due at the beginning or the end of the period. Use this function when the rate and periodic payment are known and you want to calculate how many periods are needed. ## Syntax `NPER('Rate', 'Pmt', 'Pv' [, 'Fv' [, Type]])` ## Parameters | Parameter | Description | Type | Required | Default | | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | ------- | | **Rate** | The interest rate. | Node reference | Yes | -- | | **Pmt** | Payment per period: the amount of each payment made. Payments/costs should ideally be entered as a negative number, for example `-100`, but this is not required. | Node reference | Yes | -- | | **Pv** | Present value: the current value of the annuity. | Node reference | Yes | -- | | **Fv** | Future value remaining after the final payment has been made. | Node reference | No | `0` | | **Type** | Indicates when payments are due (`1` = payment at beginning of period / annuity due, `0` = payment at end of period / ordinary annuity). Must be written as a plain number, not in quotes and not as a node reference. | Number | No | `0` | ## Watch out * `'Pv'` is the leading input node: its levels define the result's shape, and every other input is aligned to it. * Every other input may use only levels that also exist on `'Pv'`. It may use fewer levels, but not a level that `'Pv'` does not have. * `'Pmt'` is the exception: it must have exactly the same levels as `'Pv'`. * On the levels it shares with `'Pv'`, each input must cover the same level values, otherwise the rows do not line up and the function returns an error. * Each input can also be a single number. * Giving every input the same levels as `'Pv'` skips an internal alignment step and improves performance. * If costs or payments are entered as positive numbers in your model, multiply the result by `(-1)`. ## Examples ### Calculate the required number of periods This example shows a standard annuity setup with a monthly interest rate, a fixed payment, and a present value. It returns the number of periods needed until the remaining value reaches the specified future value. | Parameter | Value | | ------------------------------------------------------------------------------------------------------------- | -------- | | `Rate` (Interest Rate) | 0.045/12 | | `Pmt` (Payment per Period - Amount) | -100 | | `Pv` (Present value) | 5000 | | `Fv` (Future value) | 0 | | `Type`
Payment at Beginning of Period (Annuity Due) = 1
Payment at End of Period (Ordinary Annuity) = 0 | 0 | **Formula:** `NPER('Rate', 'Pmt', 'Pv', 'Fv', 0)` | NPER Result | | ----------- | | 55.47 | ## Related | Function | When to use instead | | -------------- | ----------------------------------------------------------------------------------- | | [RATE](/rate/) | When the number of periods is known and you want the implied interest rate instead. | | [PMT](/pmt/) | When the duration is known and you want to calculate the periodic payment instead. | --- # NPV URL: https://docs.valsight.ai/npv/ Description: Calculates the net present value of an investment from a discount rate and a series of cash flows (payments and income). **Category:** [Finance functions](/finance-functions/) ## Overview The **NPV** function **calculates the net present value of an investment** by using a discount rate and a series of future payments and income. Use this function when the discount rate is known and you want to calculate the net present value of a cash flow series. ## Syntax `NPV('Rate', 'Cashflow' [, "Level"])` ## Parameters | Parameter | Description | Type | Required | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | | **Rate** | The rate of the discount over the time of the period. | Node reference | Yes | | **Cashflow** | Series of payments or income. Negative values represent outgoing payments and positive values represent incoming payments. | Node reference | Yes | | **Level** | The period of time or a sequence over which the calculation is going to be made. If the level is not provided, the lowest time level from `'Cashflow'` is selected. | Level name | No | ## Watch out * `'Cashflow'` is the leading input node. Its levels define the result's shape, except the dimension of the discounting `"Level"`, which is aggregated away. * Rate values are percentages and must be entered and returned as decimals, for example `10% = 0.1`. * If a `"Level"` is entered, it should be a level of the `'Cashflow'` node. It should also be the lowest level in the dimension that is found in `'Cashflow'`. * The levels from the `'Rate'` input node need to be available in the `'Cashflow'` input node. * Any level that is in the same dimension as the selected `"Level"` from the `'Cashflow'` node cannot be available in the `'Rate'` input node. That also counts for all linked levels in this dimension. * The `'Cashflow'` data cannot have missing values. ## Examples ### Discount cash flows by region This example shows how a rate node and a cashflow node are combined to calculate net present value by region. The result is aggregated over the year level. **Input node:** `'Cashflow'` | Year | Region | Value | | ---- | ------ | ----- | | 2025 | Asia | +500 | | 2026 | Asia | -100 | | 2027 | Asia | +200 | | 2025 | Europe | -100 | | 2026 | Europe | +400 | | 2027 | Europe | +500 | **Input node:** `'Rate'` | Region | Value | | ------ | ----- | | Asia | 0.05 | | Europe | 0.1 | **Formula:** `NPV('Rate', 'Cashflow')` **Equivalent to:** `NPV('Rate', 'Cashflow', "Year")` | Region | NPV Result | | ------ | ---------- | | Asia | 558.26 | | Europe | 615.33 | ## Related | Function | When to use instead | | ------------ | ------------------------------------------------------------------------------------------------------ | | [PV](/pv/) | When you want the present value of an annuity-style payment stream with structured parameters instead. | | [IRR](/irr/) | When you want the implied discount rate at which `NPV = 0` instead of the discounted value itself. | --- # Number Style URL: https://docs.valsight.ai/number-style/ Description: You may customize the number rendering. You may customize the number rendering. In the global settings, you have two configuration options affecting the rendering of numbers.

Flag

Setting

Example

negativeNumberStyle

Default

-5

Parentheses

(5)

scaleStyle

Default

1,100,200,300.50 (for 1 billion + 100 million etc.

TickMarks

1"100'200,300.50

--- # oAuth 2.0 for URL External Data Source Authentication Configuration URL: https://docs.valsight.ai/oauth-2-0-for-url-external-data-source-authentication-configuration/ Description: To configure the Valsight application to allow for the use of oAuth 2.0 providers for authentication when importing an external data source for URL, edit the… To configure the Valsight application to allow for the use of oAuth 2.0 providers for authentication when importing an external data source for URL, edit the *conf/config.yml* as described below and restart the server after making changes. **NOTE:** Any oAuth 2.0 providers configured using this guide will only be available for authentication during external data source import, not for OIDC authentication to access Valsight. For details on how to configure a provider for this use case see [OpenID Connect](/openid-connect/) . In the instructions below on how configure an oAuth 2.0 provider the value **** is used several time. This a string that is used by Valsight to differentiate each provider and must be replaced with a unique value. This will also be used as the display name of the oAuth provider, presented to users when setting up an external data source. Thus, ensure that you replace each instance of **** with a value that describes the oAuth provider you are configuring, e.g. “Azure\_Active\_Directory”. **Note:** it is not possible to have any of the following characters in the **** value: `Space ! * ' ( ) ; : @ & = + $ , / ? % # [ ] " < > # % |` To configure an oAuth 2.0 client enter the following configuration keys: ``` spring: security: oauth2: client: registration: : ..... ``` **NOTE:** It is possible these keys already exist (except for ), e.g. if authentication via OpenID Connect is enabled in the application or if an oAuth 2.0 provider has been previously configured. Ensure not to modify any existing client registrations. Then configure the oAuth 2.0 client values for each provider as follows:

Configuration Key (….registration.<registration_id> →)

Description

Example Value

Default Value

client-id

OAuth 2.0 Client Identifier valid at the Authorization Server

jmxDcfi1gEffVMktJ

n/a

client-secret

Client Secret token, provided by the Authorization Server

aZWAuRZUSxT-Sh8-xDLdHI

n/a

authorization-grant-type:

The type of authorization flow to perform. This can be one of the following values:

  • authorization_code: This flow involves the user being redirect to the authentication provider to enter their credentials. Effectively they are giving Valsight permission to access the data at external data source URL.

  • client_credentials: This flow requires the Valsight application to have been given access permission to access the resource its self and does not require the user to authenticate.

authorization_code

n/a

To configure an oAuth 2.0 provider enter the following configuration keys: ``` spring: security: oauth2: client: provider: ), e.g. if authentication via OpenID Connect is enabled in the application or if an oAuth 2.0 provider has been previously configured. Ensure not to modify any existing provider registrations. Then configure the oAuth 2.0 provider values as follows: | Configuration Key (….registration.\ →) | Description | Example Value | Default Value | | -------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------- | ------------- | | issuer-uri | Identifier for the Issuer of the authorization response. | | n/a | | authorization-uri | The Authorization endpoint of the oAuth 2.0 flow | | n/a | | token-uri | The Token endpoint of the oAuth 2.0 flow | | n/a | | jwk-set-uri | The endpoint that contains certificates to verify the token | | n/a | ## Full example YAML configuration Below is an example of all the available configuration keys for an oAuth 2.0 provider, with no values supplied, for multiple registrations. ``` spring: security: oauth2: client: registration: : client-id: client-secret: authorization-grant-type: : client-id: client-secret: authorization-grant-type: provider: : issuer-uri: authorization-uri: token-uri: jwk-set-uri: : issuer-uri: authorization-uri: token-uri: jwk-set-uri: ``` --- # oAuth 2.0 with Private Key JWT Client Authentication URL: https://docs.valsight.ai/oauth-2-0-with-private-key-jwt-client-authentication/ Description: It is possible for the Valsight application to authenticate with the authorization server by creating and signing a JWT using a private key which is sent to … It is possible for the Valsight application to authenticate with the authorization server by creating and signing a JWT using a private key which is sent to the authorization server with requests. The authorization server is provided the public key to confirm the JWT has come from the application. More information can be found here: [Private Key JWT](https://oauth.net/private-key-jwt/) Before starting the configuration of the Valsight application to perform this form of client authentication, ensure the authorization server accepts the ‘`private_key_jwt`' authentication type at its token endpoint. This can normally be confirmed by looking at the authorization server‘s '.well-known/openid-configuration’ endpoint. Once confirmed you will be required to generate a private/public RSA key pair. The requirements for this are the RSA private key must be stored in the PKCS 8 format. One way to generate such a file is to use the library OpenSSL. First generate the certificate PEM file and private key in PKCS 1 format with the following command: `openssl req -x509 -newkey rsa:4096 -keyout privkeyPKCS1.pem -out cert.pem -sha256 -days 3650 -nodes` Next convert the private key to the PKCS 8 format and convert to the “key” file format with the following command: `openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in privKeyPKCS1.pem -out privKey.key` This private key should then be moved to a location that is accessible to the Valsight application, e.g. '`./conf/oidc/`'. The authorization server will then need to be configured to recognise this private key, e.g. by uploading the public key, but this may differ from provider to provider. NOTE: If you need to generate a public key for your authorization server then use the following command with OpenSSL: `openssl x509 -pubkey -noout -in cert.pem > pubkey.pem` Next update the Valsight application’s config.yaml to use ‘private\_key\_jwt’ as the authentication method for the ‘openIdConnect’ client registration by adding the following configuration keys to the config.yaml if you have a pre-existing setting: | Configuration Key (….registration.openIdConnect →) | Description | Value to Use | | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | | client-authentication-method | The type of client authentication to perform with the Authorization Server. | client\_secret\_basic | | privateRSAKeyPath | The path to the private key that is used to sign JWT tokens when using client authentication type ‘private\_key\_jwt’. The file that this path points to must be a RSA private key stored in a PKCS8 file. | Example: ./conf/oidc/privKey.key | The basic config.yaml configuration is shown below. Depending on your authorization server you may require further configuration. See OpenID Connect Configuration for details on other available settings. ``` spring: security: oauth2: client: registration: openIdConnect: client-id: client-authentication-method: private_key_jwt privateRSAKeyPath: scope: openid, valsightOpenIdConnectProperties: userProfileMapping: username: email: fullName: provider: openIdConnect: issuer-uri: authorization-uri: token-uri: jwk-set-uri: ``` --- # On-Premise Configuration Guide URL: https://docs.valsight.ai/on-premise-configuration-guide/ Description: After successful Installation, the Valsight application server should be running and should be accessible through a URL such as http://localhost:8080/. Enter… After successful [Installation](/on-premise-installation-guide/), the Valsight application server should be running and should be accessible through a URL such as . Entering this URL will bring you to the Valsight application model editing and simulation user interface. Several configuration steps are necessary before beginning to work on Value Driver Models and Simulation. --- # On-Premise Installation URL: https://docs.valsight.ai/on-premise-installation/ Description: Find specific instructions for installation and configuration of your local Valsight server. Find specific instructions for installation and configuration of your local Valsight server. --- # On-Premise Installation Guide URL: https://docs.valsight.ai/on-premise-installation-guide/ Description: The Valsight platform is a standalone server application. It is recommended to install the Valsight application on a dedicated (virtual) machine. The Valsight platform is a standalone server application. It is recommended to install the Valsight application on a dedicated (virtual) machine. ## System requirements The Valsight platform has the following minimum hardware and software requirements: ### Hardware The figures below are recommendations for a server running the Valsight platform. | Resource | Recommended | | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | CPU | x64 architecture, at least 2 GHz, 4 cores. More than 10 parallel users: 8 or more cores. | | Memory | Minimum 8 GB. More than 10 parallel users: at least 16 GB. Typical enterprise production deployments with complex models: 64 GB or more. | ### Software The server requires the following software. | Component | Requirement | | --------------------------------- | ------------------------------------------------------------------------------------ | | Operating System | Debian Stable, Ubuntu LTS, SLES 12 or later. Other Linux distributions are possible. | | Java Runtime | OpenJDK 21, 64-bit | | Model Database (production setup) | PostgreSQL 14 or later, or Microsoft SQL Server 2019 or later | The Java runtime is not part of the Valsight distribution: install OpenJDK 21 yourself and point `JAVA_HOME` at it. The startup scripts check the major version and refuse to start on anything other than 21. > **Production deployments run on Linux** > > Windows is not a supported operating system for production use. Non-production evaluation use is possible on Windows 11: see [Install an Evaluation Version on Windows](/install-an-evaluation-version-on-windows/). ### Client Each user accesses the Valsight platform from a browser, which must meet the following requirements. | Requirement | Supported versions | | ----------------- | ----------------------------------------------------------------------------- | | Operating System | Windows, Mac, Linux | | Browser | Google Chrome, Firefox, Edge - see [Supported Browsers](/supported-browsers/) | | Screen Resolution | minimum 1280×800 | | Connection | HTTPS & Secure Websockets to Valsight Cloud or On-Premise Server | ### Intermediate proxies & loadbalancers Any proxy or load balancer between the client and the server must meet the following requirement. | Requirement | Recommended | | ----------- | ---------------------------- | | Websocket | Proxy Support for Websockets | ## Installation steps ### Requirements Install the requirements listed above on the target machine. Make sure the `JAVA_HOME` environment variable is set. ### Unpacking Extract the supplied ZIP file (e.g. *valsight-server-7.0.14.zip*) to the desired install location, without spaces in the name. On Linux, this could be `/opt/valsight` and on Windows `C:\valsight` ### Configuration In the *conf/* directory: copy *config.yml.default* to *config.yml* and edit the file accordingly. While the standard settings work, consider to setup a production database. ## Launching the server The Valsight application is launched using the supplied scripts, depending on the operating system: ### Linux Execute the script `bin/valsight-server` from the command line. You may set up an initscript to run the service repeatedly or on system startup. Make sure to set the service's working dir to the installation dir (and not bin/). ### Windows (Non-Production setups only) Execute the script `bin\valsight-server.bat` from a command line or by double-clicking in Windows Explorer. ## Configuration The Valsight application is now running on port 8080 and you can access it using a browser by entering `http://localhost:8080` into the address bar. The default username and password is "admin" and "admin". ### Adding a license file The license file needs to be put into the main directory of the application as "*license.pem*" (i.e. at the same level as the *conf*, *lib* and *bin* folders.) Alternatively, the license can be uploaded on the first start of the server. Opening the URL above will bring you to the configuration page (`http://localhost:8080/system/config`) after starting the server for the first time. Before using the server, you need to add a valid license file. * In the file upload form in the upper part of the configuration dialog, select the license file which was provided to you * Press "Update License Key" to submit the form * The server should respond "License file uploaded successfully" and the license key information should be visible under "Current License" ![Screen Shot 2015-07-14 at 11.06.09.png](./images/5094192637.png) ### Configuring a model database By default, the Valsight application will use a file-based internal database to store model configurations (the database files are located under `db/*.db`). For a growing production setup, it is recommended to use a dedicated database to store model configurations. The exact steps necessary will vary depending on the chosen database, but the general process is as follows: 1. Set up a supported database system 2. Create a dedicated database user for use by the Valsight application 3. Create a dedicated database and grant permissions to the user created in the previous step. 4. If using a MS SQL database ensure the setting READ\_COMMITED\_SNAPSHOT is enabled, more information can be found here 5. In the Database Configuration form on the system configuration page (see above), enter the details to access your database 6. Press "Update Database Configuration" to save the configuration (it is stored in the config file `conf/config.yml`) 7. Re-start the Valsight application server to use the newly configured database. You will start with an empty database (information from the previously configured model database is not copied over). Troubleshooting, hints & tips: * Postgresql of many distributions is often not configured for TCP/IP access and allowance of password based authentication. Make sure that *psql -h 127.0.0.1 -U username* allows you to connect to the database. * If you like to configure SSL, you can do so by adding the correct parameters to the JDBC string, e.g. for Postgresql extend the URL with ?ssl=true and enable SSL in the server settings. ##### conf/config.yml ``` # Excerpt from conf/config.yml# environments: production: dataSource: driverClassName: org.postgresql.Driver sqlDialect: org.hibernate.dialect.PostgreSQLDialect # Alternative MSSQL: # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver # sqlDialect: org.hibernate.dialect.SQLServerDialect # username: password: url: jdbc:postgresql://localhost:5432/es-rest-service ``` ### Configuring an HTTPS proxy > **Websockets** > > The application requires the support of websockets, please make sure that any used proxy is able to forward requests accordingly. In a production setup, it is recommended to add HTTPS protection to the Valsight application. In a typical setup, an HTTP server such as Apache 2.0 would be set up "in front of" the Valsight application with a reverse proxy setup to port 8080. The exact steps necessary will vary depending on the chosen HTTP server, but a sample Apache 2.0 configuration could look like this: ##### /etc/apache2/sites-available/valsight.conf ``` ServerName simulation.company.com Redirect permanent / https://simulation.company.com/ NameVirtualHost *:443 ServerName simulation.company.com # Reverse Proxy Settings ProxyPass / http://localhost:8080/ ProxyPassReverse / http://localhost:8080/ ProxyPreserveHost On # Rewrite WSS requests to WS RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteRule ^/(.*) ws://localhost:8080/$1 [P,L] SSLEngine on RequestHeader set X-Forwarded-Proto "https" SSLCertificateFile /etc/ssl/certs/simulation_service_https.pem SSLCertificateKeyFile /etc/ssl/private/simulation_service_https.key SSLHonorCipherOrder on # Enable this if you want HSTS (recommended) Header add Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" BrowserMatch "MSIE [2-6]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 # MSIE 7 and newer should be able to use keepalive BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown ``` ## First steps Please add at least one default data source with an empty xlsx file before using the software. See [Data Source Upload](/data-source-upload/) for the basic steps. To get started with the software, work through [Tutorial: Build a Valsight Project](/getting-started/). ## Upgrade steps To move an existing installation to a newer version, follow [Update / Upgrade the installation](/update-upgrade-the-installation/). Always create a database backup first. --- # OpenID Connect URL: https://docs.valsight.ai/openid-connect/ Description: To configure the Valsight application to use the OpenID Connect SSO, edit conf/config.yml and restart the server after making changes. To configure the Valsight application to use the OpenID Connect SSO, edit *conf/config.yml* and restart the server after making changes. To enable OpenID Connect login configure the following value: | Configuration Key (loginMethodConfigurations → openIdConnect →) | Description | Example Value | Default Value | | --------------------------------------------------------------- | ----------------------------------------------------------- | ------------- | ------------- | | enabled | Whether OpenID Connect authentication should be used or not | true | false | To configure an OpenID Connect client enter the following configuration keys: ``` spring: security: oauth2: client: registration: openIdConnect: ..... ``` Then configure the OpenID Connection client values as follows: | Configuration key | Description | Example | Default | | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------- | -------------------------------- | | `client-id` | OAuth 2.0 client identifier, valid at the authorization server | `jmxDcfi1gEffVMktJ` | n/a | | `client-authentication-method` | The type of client authentication to perform with the authorization server. See [Client authentication methods](#client-authentication-methods). | `client_secret_basic` | `client_secret_basic` | | `client-secret` | Client secret token, provided by the authorization server. Since 6.3.0 this is no longer mandatory unless `client_secret_basic` is the client authentication mode. | `aZWAuRZUSxT-Sh8-xDLdHI` | n/a | | `scope` | Comma-separated list of scopes to request, when additional claims are needed | `openid, email, profile` | n/a | | `provider` | The name of the OpenID Connect provider to use. Required unless a provider with the registration id `openIdConnect` exists. | `openIdConnect` | n/a | | `valsightOpenIdConnectProperties → userProfileMapping → username` | The claim used to uniquely identify a user. Must always be present in the provider's response, and unique per user. See [Claim names are case sensitive](#claim-names-are-case-sensitive). | `preferred_username` | `sub` | | `valsightOpenIdConnectProperties → userProfileMapping → email` | The claim that contains the user's e-mail address. Optional. | `email` | n/a | | `valsightOpenIdConnectProperties → userProfileMapping → fullName` | The claim that contains the user's full name. Optional. | `name` | n/a | | `valsightOpenIdConnectProperties → loginSuccessfulUrl` | The absolute URL, starting with `http` or `https`, of the application's main page. The user is redirected there after a successful login. | `https://valsight.example.com/` | n/a | | `valsightOpenIdConnectProperties → forceGroupsOverage` | Forces the application to always use the `https://graph.microsoft.com/v1.0` API to fetch the user's groups. No effect unless `groupsClaim` is enabled. Optional. | `true` | `false` | | `valsightOpenIdConnectProperties → acr_values` | Passes additional authentication-related information to the user service. Optional. | `myvalue1:myvalue2:myvalue3:myvalue4` | n/a | | `valsightOpenIdConnectProperties → mandatoryClaims` | Customizes which claims must be present, and with which values, beyond those requested by the OpenID Connect specification. See [Mandatory claims](#mandatory-claims). Optional. | See [Mandatory claims](#mandatory-claims) | n/a | | `valsightOpenIdConnectProperties → groupsClaim` | The claim holding the groups the user belongs to. See [Group synchronization](#group-synchronization). Optional. | `groupsInOpenIDConnectResponse` | n/a | | `valsightOpenIdConnectProperties → requiredGroupNamePrefix` | Removed in 6.0.0. See [Removed: requiredGroupNamePrefix](#removed-requiredgroupnameprefix). | `AcceptedGroup_` | n/a | | `valsightOpenIdConnectProperties → userInfoEndpointScopes` | Scopes that are accessible only from the user info endpoint, not from the token. See [User info endpoint scopes](#user-info-endpoint-scopes). | See [User info endpoint scopes](#user-info-endpoint-scopes) | `profile, email, address, phone` | Three further settings under `valsightOpenIdConnectProperties` control what the login page offers and which scopes each login option requests: `buttonText` (see [Login button label](#login-button-label)), `additionalScopes` (see [Additional scopes](#additional-scopes)), and the `alternativeLogin` group (see [Alternative login flow](#alternative-login-flow)). ### Client authentication methods The supported forms of authentication are `client_secret_basic` and `private_key_jwt`. With `client_secret_basic` a `client-secret` must be provided; with `private_key_jwt` a `privateRSAKeyPath` must be provided instead. For more on `private_key_jwt`, see [OAuth 2.0 with private key JWT client authentication](/oauth-2-0-with-private-key-jwt-client-authentication/). ### Claim names are case sensitive Ensure the configured string matches the IdP claim name exactly. This applies to every `userProfileMapping` entry, to `groupsClaim`, and to the `claim` values under `mandatoryClaims`. ### Mandatory claims Every claim configured here must be present in the provider's response and carry the specified value. Where a claim has multiple values in the response — a list of the user's groups, for example — one of those values must match the configured value exactly. MIGRATETOKEN1ENDTOKEN ### Group synchronization Setting `groupsClaim` turns on group synchronization. If the claim is absent or empty, groups must be managed inside the application instead. The value should be a claim name that contains the groups the provider supplies. Group matching then happens as follows: 1. Read the groups from the OpenID Connect response. 2. Create groups that are missing in the application. 3. Add the user to all groups from the response. 4. Remove the user from all groups not in the response. This functionality never automatically deletes groups in the application. ### Removed: requiredGroupNamePrefix Available since 5.9.1, removed in 6.0.0 and replaced by `loginMethodConfigurations → commonSSOOptions → requiredGroupNamePrefixes`. See [Common SSO Options](/common-sso-options/). Before 6.0.0 this determined whether group names had to carry a given prefix to be recognised by the application: any group name in the OpenID Connect response not starting with the value was treated as absent. When `mandatoryGroupName` was also set, the mandatory group name had to carry the required prefix. ### User info endpoint scopes To stop the user info endpoint being invoked at all, populate this list with none of the scopes listed under `scope`. Setting it to an empty list means the user info endpoint is always invoked. Available since 6.0.26. MIGRATETOKEN2ENDTOKEN ### Login button label Available since 7.2.5 and 7.3.0. | Configuration key | Description | Example | Default | | ---------------------------------------------- | --------------------------------------------------------------- | --------------------- | ---------------- | | `valsightOpenIdConnectProperties → buttonText` | Label of the OpenID Connect button on the login page. Optional. | `Log in with Acme ID` | `OpenID Connect` | This key sets a default, it does not override: whatever an administrator has saved under **Login Page Settings** wins whenever it is set. See [Login Page Customization](/login-page-customization/) for that setting. Use `buttonText` to ship a label together with the configuration file, so a newly installed instance already shows the right wording before anyone opens the settings page. If neither is set, the button reads *OpenID Connect*. ### Additional scopes Available since 7.2.5 and 7.3.0. | Configuration key | Description | Example | Default | | ---------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------- | ------- | | `valsightOpenIdConnectProperties → additionalScopes` | Scopes the login button requests in addition to those listed under `scope`. Optional. | `urn:zitadel:iam:org:id:123456789456132` | n/a | Write the value either as a YAML list or as a single string with the scopes separated by commas, whitespace, or both. The scopes are added to `scope`; nothing is removed. The typical use is an identity provider that accepts an organization scope. Sending it pins the login to one organization, so the user reaches their own identity provider directly instead of first having to enter an email address for domain discovery. That same scope excludes everyone who is not a member of that organization. Those users need the alternative login flow. ### Alternative login flow Available since 7.2.5 and 7.3.0. A second login option that requests a different set of scopes from the same OpenID Connect client. It exists for the users an organization scope in `additionalScopes` would otherwise lock out, for example staff who authenticate against a different organization's identity provider. | Configuration key (`valsightOpenIdConnectProperties → alternativeLogin →`) | Description | Example | Default | | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------------- | | `additionalScopes` | Scopes this flow requests instead of `additionalScopes`. May be left empty. See [An empty scope list is a valid configuration](#an-empty-scope-list-is-a-valid-configuration). Optional. | `urn:zitadel:iam:org:id:987654321098765` | n/a | | `buttonText` | Label of the link on the login page. Without it the flow stays reachable by its URL but is not listed. Optional. | `Log in with a different organization` | n/a | | `enabled` | Switches the flow on or off explicitly. See [When the enabled key is needed](#when-the-enabled-key-is-needed). Optional. | `false` | On when `additionalScopes` or `buttonText` is set | | `requiredHeader` | Lists the link only for clients whose request carries this header. See [Listing the link for some clients only](#listing-the-link-for-some-clients-only). Optional. | `x-internal-client` | Unset, so the link is listed for every client | The flow is requested with a query parameter on the authorization URL: ``` //oauth2/authorization/openIdConnect?loginFlow=alternative ``` That parameter only selects between scope sets already configured on the server. An absent, unknown, or unconfigured value falls back to the primary scopes, so no caller can request scopes of their own. On the login page the option is rendered as a link below the OpenID Connect button rather than as a second button, because it is a variant of the same provider and not a login method of its own. #### When the enabled key is needed Configuring either `additionalScopes` or `buttonText` under `alternativeLogin` already enables the flow, so most instances need no `enabled` key at all. Set it explicitly in two cases: * `enabled: true` for a flow that has neither scopes nor a label of its own, which is otherwise indistinguishable from an unconfigured one. * `enabled: false` to switch a configured flow off without deleting its keys. #### An empty scope list is a valid configuration Leaving `alternativeLogin → additionalScopes` empty is a meaningful configuration rather than a pointless one. The flow then sends only the scopes listed under `scope`, and so no organization scope at all, which is what makes the identity provider fall back to its own account chooser. For that reason the alternative flow never falls back to the primary `additionalScopes`. Once the flow is enabled, requesting it always replaces the primary scopes, even when it defines none. #### Listing the link for some clients only Name a request header in `requiredHeader` and the link is listed only for clients whose request carries it; leave the key unset and the link is listed for everyone. Use it where a login page carries one customer's branding and the alternative option is meant for a different group of users — staff, say — who can be told apart by something the infrastructure in front of Valsight already knows. Which clients get the header is decided in that infrastructure and not in Valsight. The application never interprets the value, only whether the header is there with a non-blank value, so the header can mean whatever the deployment needs it to mean. Two requirements on whichever component injects it: * It has to set the header on **every** request, so that a copy sent by the client is always overwritten. If a client could supply the header itself, the setting would gate on nothing. * It has to be a component the request cannot bypass. Valsight reads the configured header alone, with no fallback to `X-Forwarded-For` or `X-Real-IP`, because a client writes those freely. See [Reverse Proxy](/reverse-proxy/). Hiding the link decides what the login page offers; it is not an access rule. The flow's URL keeps working without the header, and opening the login page with `?alternativeLogin=1` lists the link for any client: ``` //app/index.html#/login?alternativeLogin=1 ``` Give that URL to the users the flow is for who reach the login page without the header. Where nothing injects the header, no client ever carries it and the link is only reached this way — so leave `requiredHeader` unset until the header is actually in place. While `requiredHeader` is set, the login page's data response carries a `Vary` header naming it, so a cache between Valsight and the browser cannot serve one client's login page to another. #### Example configuration ``` spring: security: oauth2: client: registration: openIdConnect: scope: openid, email, profile valsightOpenIdConnectProperties: buttonText: Log in with Acme ID additionalScopes: urn:zitadel:iam:org:id:123456789456132 alternativeLogin: # deliberately empty: send no organization scope at all additionalScopes: buttonText: Log in with a different organization requiredHeader: x-internal-client ``` With this configuration the login page shows one **Log in with Acme ID** button that pins the login to the Acme organization. Clients whose request carries `x-internal-client` additionally get a **Log in with a different organization** link below it, which sends no organization scope. Drop the `requiredHeader` line to offer that link to everyone. To configure an OpenID Connect provider enter the following configuration keys: ``` spring: security: oauth2: client: provider: openIdConnect: ..... ``` Then configure the OpenID Connection provider values as follows: | Configuration Key (….provider.openIdConnect →) | Description | Example Value | Default Value | | ---------------------------------------------- | ----------------------------------------------------------- | ---------------------------------- | ------------- | | issuer-uri | Identifier for the Issuer of the authorization response. | | n/a | | authorization-uri | The Authorization endpoint of the OpenID Connect flow | | n/a | | token-uri | The Token endpoint of the OpenID Connect flow | | n/a | | jwk-set-uri | The endpoint that contains certificates to verify the token | | n/a | #### Full example YAML configuration Below is an example of all the available configuration keys for OpenID connect, with no values supplied except where stated: ``` spring: security: oauth2: client: registration: openIdConnect: client-id: client-secret: scope: valsightOpenIdConnectProperties: userProfileMapping: username: email: fullName: forceGroupOverage: loginSuccessfulUrl: mandatoryClaims: #example value group: groupName acr_values: groupsClaim: requiredGroupNamePrefix: userInfoEndpointScopes: provider: openIdConnect: issuer-uri: authorization-uri: token-uri: jwk-set-uri: ``` ## Logging For logging purpose, add in the log level view (Configuration UI), the following package: * `org.springframework.security` * `org.springframework.security.oauth2` * `com.valsight.authentication.oauth` * `com.valsight.services.authentication.SSOService` * `com.valsight.authentication` * `org.springframework.web.client` Set the log level to DEBUG ### Redirect/callback URL When configuring the IdP the redirect/callback URL for the application is: \//login/oauth2/code/openIdConnect ### Reverse proxy configuration If the application is running behind a reverse proxy it will be required to configure the reverse proxy such that the OpenID connect authentication flow can be performed A guide to doing this can be found here: [Reverse Proxy](/reverse-proxy/) --- # Operators URL: https://docs.valsight.ai/operators/ Description: Operators are the basic building blocks used in formulas to combine values, compare results, and create conditions. They are used directly in formulas, and often inside functions such as IF. Operators are the basic building blocks used in formulas to **combine values, compare results, and create conditions**. They are used directly in formulas, and often inside functions such as `IF`. Use this section to understand operator behavior and navigate to the relevant reference page. ## Start here if you want to: | If you | Go to | | ------------------------- | ------------------------------------------------------------------ | | Calculate numeric results | [Arithmetic operators](/arithmetic-operators/) | | Build a condition | [Comparisons & boolean operators](/comparisons-boolean-operators/) | | Write conditions for `IF` | [Logical functions](/logical-functions/) | ## Quick rules * Use parentheses to make intent explicit * Without parentheses, operators bind in six levels, loosest first: `\|\|`, then `&&`, then `=` and `!=`, then `<` `<=` `>` `>=`, then `+` and `-`, then `*` `/` `%` * Arithmetic therefore binds tighter than any comparison, so `'A' + 1 > 'B'` is read as `('A' + 1) > 'B'` * Functions evaluate inside out * `+` and `-` aggregate both inputs to their common dimensions (the intersection of the shared dimensions) * `*`, `/` and `%` calculate across the combined dimension set (the union of both inputs’ dimensions) ## Related * [Formula basics](/formula-basics/): parentheses, evaluation order, notation * [Function catalog](/function-catalog/): functions used together with operators * [Troubleshooting guide](/troubleshooting-guide/): common pitfalls with comparisons and missing values --- # OR (||) URL: https://docs.valsight.ai/or/ Description: Returns 1 (true) if at least one of two inputs is true; otherwise returns 0 (false). Non-zero values are treated as true, while 0 is treated as false. **Category:** [Logical functions](/logical-functions/) ## Overview The **OR** function **connects two inputs with the logical OR** and returns true (1) if at least one of the values is true and false (0) otherwise. Use this function when you need a 1/0 flag that becomes true as soon as at least one of two inputs is true. ## Syntax `OR('Node1', 'Node2')` `'Node1' || 'Node2'` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | | **Node2** | Second input node. | Node reference | Yes | ## Watch out * A row that exists in only **one** of the two inputs is still evaluated. The missing side counts as false, so such a row returns 1 if the value that is there is non-zero and 0 otherwise. The row is never dropped, and the result covers every row of both inputs together. ## Examples ### Typical use This example shows that `OR` returns 1 when at least one of the two inputs is true. Non-zero values are treated as true, while 0 is treated as false. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 17 | | 2026 | 0 | | 2027 | 0 | | 2028 | 1 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 1 | | 2026 | 0 | | 2027 | 1500 | | 2028 | 0 | **Formula:** `OR('A', 'B')` | Year | OR Result | | ---- | --------- | | 2025 | 1 | | 2026 | 0 | | 2027 | 1 | | 2028 | 1 | ## Related | Function | When to use instead | | ----------------- | -------------------------------------------------------------------------------------- | | [AND (&&)](/and/) | When both inputs must be true at the same time instead of just one of them. | | [XOR](/xor/) | When exactly one of the two inputs should be true instead of allowing both to be true. | --- # Overlapping Data Labels URL: https://docs.valsight.ai/overlapping-data-labels/ Description: Why some data labels are missing when they collide in a chart, and the two ways to get the values back. Where data labels overlap in a chart, not all values can be shown. The values are still correct, only some of the labels are dropped. ## Which label wins In **area charts** and **line charts**, the sort order of the nodes decides which label wins. If a chart shows two nodes and node B is sorted above node A, the chart prioritizes node B's label, so where labels collide only node B's is shown. ![A chart showing only node B's label where the two collide](./images/5094216526.png) This does not mean the numbers are wrong. ## Reorder the nodes To change the priority, reorder the nodes: in the **Axes** section of the chart editor, click the sort button next to the level the nodes sit on and drag them into the order you want. See [Sorting Level Values](/sorting-level-values/). ## Show a total instead The other route is [stack totals](/stacking-and-stack-totals/). Below, the **Combined sum** option shows the total of both nodes instead of the two colliding labels. ![The same chart with a combined sum instead of colliding labels](./images/5094216461.png) Data behind both examples: | Node | 2021 | 2022 | | ---- | ---- | ---- | | A | 4000 | 6000 | | B | 30 | 50 | ## Related * [Sorting Level Values](/sorting-level-values/): the order that decides which label wins. * [Stacking and Stack Totals](/stacking-and-stack-totals/): stack the data series and label the total of each stack. * [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/): hide the values of one data series entirely. --- # Overwriting Project Variables URL: https://docs.valsight.ai/overwriting-project-variables/ Description: Variable values defined at the project level can be overridden per scenario in the Scenario Manager. This makes it possible to simulate different planning as… Variable values defined at the project level can be overridden per scenario in the Scenario Manager. This makes it possible to simulate different planning assumptions, such as a different start year or growth rate, without modifying the underlying model. ## When to use it * When key assumptions differ between scenarios and should not affect the shared model * When you want to quickly compare outcomes across scenarios by adjusting a single value * When you need to lock a variable value for a scenario, independent of future changes to the project default ## How it works Each scenario can carry its own version of a variable value, independent of the project-level default. The Scenario Manager displays the number of overridden variables per scenario, giving a quick overview of where scenarios diverge from the baseline. ![number of changed variables.png](./images/6880591873.png) ## Overwriting a variable Open the Scenario Manager and edit the desired scenario. The *Manage scenario* window allows you to change scenario settings (name, description, based on, color) as well as the values of scenario variables. Video: [Overriding Variables in SM](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6880624641_Overriding-Variables-in-SM.mov) ## Pinning a variable value By default, a scenario variable dynamically follows the project-level default. To freeze it at a specific value (so it stays the same even if the project default changes later), simply type the desired value directly into the scenario variable field. For example, if the current period is set to `2026` at the project level and you want a specific scenario to always use `2026` regardless of future updates, enter `2026` manually in that scenario's variable field. From that point on, the scenario will retain `2026` even if the project default changes to `2027`. To go back to following the project default dynamically, clear the value from the input field. ## Limitations > **Sharing scenarios with overwritten variables is not supported.** The scenario can be shared, but overwritten values are not transferred. Variables must be set manually in the receiving scenario. ## Related * [Project Variables](/project-variables/) * [Using Project Variables in Node Formulas](/using-project-variables-in-node-formulas/) --- # Parallel Access URL: https://docs.valsight.ai/parallel-access/ Description: With the functionality of parallel access, Valsight enables users to: With the functionality of parallel access, Valsight enables users to: * work with multiple users in the same workspace without interfering with each other and creating ambiguous states * open the same workspace in multiple tabs while working with the same user * see which users are currently active in the same workspace * the folding/unfolding of assumptions, the search function and the hiding/showing of columns is not synced across users to enable a fluent collaboration with user a user specific Scenario Manager view ![Parallel Access.gif](./images/5155520674.gif) ## Locking To avoid ambiguous states in a workspace, certain actions can only be done by one user/in one tab at a time. These actions are: * Editing a line-item * A line-item is locked while a user is editing either the data or the details * Other users can enter the line-item in a read-only mode and are not able to edit anything until the other user exited the line-item again * The read-only state is decided when the line-item is opened and is deliberately not refreshed while you sit in it. Once the other user leaves, close the line-item and open it again to get edit rights * Editing a chart * Like line-items, charts are locked while a user is editing a chart. * For charts, other users will be blocked to open the chart editor of a chart that is currently edited, but will receive a notification that someone else is currently editing the chart A lock does not have to be given back by hand. It expires roughly 70 seconds after the last sign of life from the browser that holds it, and a sweep every few seconds releases the expired ones, so a colleague who closes their laptop mid-edit stops blocking the workspace within about a minute rather than indefinitely. > Locks belong to a browser **tab**, not to a user. Opening the same workspace in a second tab and editing there means the two tabs compete for the same locks, so you can lock yourself out. ## Limitations * It is recommended to only access the same workspace with a maximum of four users at the same time * Sheets can be deleted while other users are looking at these sheets. * Deleting line-items or charts while another user is editing them is not possible --- # Parallel Access in the Model Editor URL: https://docs.valsight.ai/parallel-access-in-the-model-editor/ Description: Parallel editing allows multiple users to access and work on the same model simultaneously in the Model Editor. This feature significantly improves collabora… Parallel editing allows multiple users to access and work on the same model simultaneously in the Model Editor. This feature significantly improves collaboration, particularly for teams managing complex models, by removing the need to force others out of the model to make changes. Objects such as nodes and annotations can now be viewed and edited collaboratively in real time, with clear indicators showing who is currently editing what. ## Key benefits * Multiple users can open, view, and work on the same model at the same time. * Objects being edited are automatically locked for others to prevent conflicts. * Locked objects remain visible in **read-only mode**. * ![Model Editor\_PAX.png](./images/6877511709.png) The header displays a list of all users currently active in the model. * Real-time synchronization ensures changes are instantly reflected for all users. ## How it works ### Live collaboration * As soon as a user edits a node or annotation, it becomes locked to others. * Other users can still **view** the object (including its properties), but cannot make changes until the lock is released. * The locking user’s **initials and name** appear as an icon directly on the object. * ![Model Editor\_PAX user.png](./images/6877970441.png) Changes are instantly synced across all open sessions; no manual refresh required. ### Locked objects The following actions are **blocked** for locked objects: | Object Type | Blocked Actions | | --------------- | ---------------------------------------- | | **Nodes** | Editing operations or metadata, deleting | | **Annotations** | Editing, deleting, moving or resizing | However, locked objects can still be **copied**. > ⚠️ Swimlanes are not subject to locking and remain editable by all users. ### Viewing activity * All active users are shown in the model header as a dropdown with initials and full names. * ![Model Editor\_PAX in this model.png](./images/6878494741.png) View-only users can also see the active user list and locked object indicators. ### Lock handling & timeouts * If a user disconnects while editing an object, the lock is automatically released after a short timeout. * There is **no option to forcefully remove** another user or override a lock. ## Access & permissions * No special permission is required to use parallel editing. * **Edit rights** are required to make changes or lock objects. ## Limitations * While model objects are synced in real time to the workspace, **charts and validation results do not automatically reload**. Manual refresh may be required to see updates reflected elsewhere. * Only one user can edit a given object at a time. ## Summary Parallel Editing in the Model Editor brings Valsight's collaborative capabilities to the core of model development. With real-time sync, live user indicators, and automatic locking, teams can now build and refine models together, without interruption. This feature enables: * Seamless collaboration for distributed teams * Safe, conflict-free editing * Greater transparency into who is working where in the model Whether you're troubleshooting a complex driver tree or fine-tuning annotations, you can now do it together, in the same model, at the same time. --- # Part 1: Create a Project URL: https://docs.valsight.ai/part-1-create-a-project/ Description: In this part, you create a new Valsight project and define its time horizon. In this part, you create a new Valsight project and define its time horizon. **Projects** in Valsight are the **top-level containers** that bundle together dimensions, data sources, models, workspaces, and scenarios for a specific planning use case. For detailed reference on any of the concepts here, see [Projects](/projects/). ## Watch the video guide Video: [CreateProject](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6889537574_CreateProject.mp4) ## Steps ### Open the project overview After logging in to Valsight, the **Project overview** appears. This is the start page that lists all projects you have access to. ### Create a new project 1. Click **Add** in the upper right corner of the project overview. 2. Enter the following details: | Field | Value | Notes | | ------------------------------ | ------------------------- | -------------------------- | | Name | Revenue Planning Tutorial | Choose a descriptive name. | | [Business Key](/business-key/) | REVENUE\_TUTORIAL | This must be unique. | ### Set the time horizon Configure the [time horizon](/project-settings/) in the project creation dialog: | Setting | Value | Notes | | -------------- | ----- | --------------------------------------- | | Horizon Period | Year | Can also be Month or Quarter. | | From | 2025 | The first year in your data. | | To | 2029 | The last year of your planning horizon. | ### Save the project 1. Click **Create**. 2. The project appears in the project overview. 3. Click the project name to open it. After opening the project, you will see an empty project with sections for workspaces, models, dimensions, and data sources. ## What you have done * Created a new project called `Revenue Planning Tutorial` * Set the time horizon to years from 2025 to 2029 * Opened the project, ready for the next steps --- # Part 2: Set Up Dimensions URL: https://docs.valsight.ai/part-2-set-up-dimensions/ Description: In this part, you create the dimensions, levels and level values. In this part, you create the dimensions, levels and level values. **Dimensions** in Valsight **structure data into cluster** such as product, region, or time, so values can be organized, aggregated, and analyzed across different views. For detailed reference on any of the concepts here, see [Dimensions](/dimensions/). ## Watch the video guide Video: [CreateDim](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6892257281_CreateDim.mp4) In this tutorial, you will use: * **Time:** predefined by Valsight * **Product:** Premium, Standard * **Location**: France, Germany, USA, Canada, grouped into regions: Europe, America The Location dimension uses a hierarchy: * **Region** * **Country** ![Data cube showing the Region and Product dimensions with sample aggregated values by year](./images/6893436948.png) ## Steps ### Create the product dimension 1. Open **Dimensions** from the left menu bar. 2. Click **Add** to create a new dimension. 3. Enter the dimension details: | Field | Value | Notes | | -------------- | ------- | ------------------------------------------------------------------------------ | | Dimension name | Product | The name can be chosen freely. | | Level name | Product | This **must** match the column name in the Excel file exactly, case-sensitive. | * Click **Confirm** to create the dimension. * Add the level values: * Premium * Standard *Tip: Level values can also be added later during data upload if they are missing.* ### Create the location dimension 1. In the Dimension Manager, click **Add**. 2. Enter the dimension details: | Field | Value | Notes | | -------------- | -------- | ------------------------------------------- | | Dimension name | Location | | | Level name | Region | Start with the highest level. | | Level name | Country | Hit **Shift + Enter to add another level**. | 3. Click **Confirm**. 4. Add the level values. | Region | Country | | ------- | ------- | | Europe | France | | Europe | Germany | | America | USA | | America | Canada | ## What you have done * Created the **Product** dimension * Created the **Location** dimension with a Region > Country hierarchy * Added the level values needed for the tutorial data --- # Part 3: Upload Data URL: https://docs.valsight.ai/part-3-upload-and-validate-data/ Description: In this part, you upload the sample Excel file and validate that it matches the project dimensions. In this part, you upload the sample Excel file and validate that it matches the project dimensions. **Data** in Valsight provides the **input values that feed models** and serve as the baseline for calculations, simulations, and analysis. For detailed reference on any of the concepts here, see [Data Import & Export](/data-import-export/). ## Watch the video guide Video: [DataSource](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6892519508_DataSource.mp4) ## Sample file Use one Excel file with one worksheet named **Price and Volume**. ### Required columns | Column | Type | Notes | | --------- | --------------- | ----------------------------------------------- | | `Year` | Dimension level | System default time level. Must be named `Year` | | `Product` | Dimension level | Must match the Product level name exactly | | `Country` | Dimension level | Must match the Country level name exactly | | `Price` | Measure | Used later in model calculations | | `Volume` | Measure | Used later in model calculations | ### Example data ![Sample Excel data with Year, Product, Country, Price, and Volume columns](./images/6892421133.png) **Before you upload, make sure:** * Data starts in the first row * Cells are not empty * No sheet name or column header starts with `#`, or it is skipped on import * The worksheet contains only the upload data ## Steps ### Upload the data source 1. Open **Data Sources**. 2. Click the green **New Datasource** dropdown and pick **XLSX**. 3. Choose your sample file. The Data Source Type is already set and shown read-only, so there is no file type to select in the form. 4. Enter `TutorialData` as the name for the data source. 5. Click **Create Data Source**. ### Validate dimensions After upload, Valsight checks whether the values in your file match the dimensions in the project. 1. Click **Validate dimensions**. 2. Check the **Errors** tab for any validation messages. 3. If level values are missing, click on the **Dimension Management** tab and add them. 4. Return to the validation result and verify that there are no errors. *Important: To add missing level values during upload, all levels must be present in the data source. For example, to fill missing values for* `Country`*, the corresponding* `Region` *values must also exist in the upload.* ## What you have done * Uploaded the sample file as `TutorialData` * Validated that the file matches the project dimensions --- # Part 4: Build the Driver Model URL: https://docs.valsight.ai/part-4-build-the-driver-model/ Description: In this part, you create two models and build the cause-effect relations of the revenue model. In this part, you create two models and build the cause-effect relations of the revenue model. **Models** in Valsight define the **underlying calculation logic** that connects data, business logic, and drivers as the basis for scenario simulation. For detailed reference on any of the concepts here, see [Modeling](/modeling/). ## Watch the video guide Video: [DriverModel](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6895697921_DriverModel.mp4) ## The model structure Driver models in Valsight follow the "Valsight Fish" structure, read from right to left. ![Valsight Fish diagram showing model layers from Data base and Driver on the right through Business models and P\&L to KPIs on the left](./images/6892978181.png) For this tutorial, you will create two models: * **500\_Data**: contains the base nodes that pull in the Excel data * **100\_P\&L**: contains the drivers, calculation logic, and the revenue result ## Steps ### Create the models 1. Open the **Model overview** from the left menu bar. 2. Click **Add** to create the two models: | Field | `500_Data` | `100_P&L` | | ----------- | -------------------- | ------------------------------- | | Description | Base data from Excel | Revenue calculation and drivers | | Submodels | None | `500_Data` | 3. Click **Create**. ### Build the `500_Data` model The data model contains two base nodes that connect to the uploaded Excel data: one for volume and one for price. 1. Open the **500\_Data** submodel by clicking its name. 2. Click the **Node** button in the **action bar** at the bottom of the canvas. 3. Create two **Data nodes**: | Node | Unit | | --------------- | ---------------- | | `Volume (Base)` | `Quantity` | | `Price (Base)` | `EUR / Quantity` | 4. Select a node, click the **Data** button in the function editor, choose **Data source, Table and Measure** in the dialog, then click **Insert** to connect it via the [DATA](/data/) function: | Node | Formula | | --------------- | ---------------------------------------------------- | | `Volume (Base)` | `DATA("TutorialData", "Price and Volume", "Volume")` | | `Price (Base)` | `DATA("TutorialData", "Price and Volume", "Price")` | Use **Data Preview** to confirm that both nodes show 2025 values. ### Build the 100\_P\&L model Switch to **100\_P\&L** using the **model selector** in the header at the top left of the Model Editor. Create the following nodes: | Node | Type | Unit | | ------------------ | ---------- | ---------------- | | `Volume` | Standard | `Quantity` | | `Market Growth` | Simulation | `Percent` | | `Price` | Standard | `EUR / Quantity` | | `Price Adjustment` | Simulation | `EUR` | | `Revenue` | Standard | `EUR` | Then set each node's formula: | Node | Formula | | ------------------ | ---------------------------------------------------------- | | `Volume` | `ROLLFORWARD_ADVANCED('Volume (Base)', 'Market Growth')` | | `Market Growth` | `EXPAND(0, "Year", "Region")` | | `Price` | `ROLLFORWARD_ADVANCED('Price (Base)', 'Price Adjustment')` | | `Price Adjustment` | `EXPAND(0, "Year", "Product", "Country")` | | `Revenue` | `'Volume' * 'Price'` | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) carries the 2025 base values forward into future years; [EXPAND](/expand/) creates a dimensional structure for an empty node. `Price Adjustment` must match the dimensions of `Price (Base)`. Use **Data Preview** to confirm that Revenue equals Volume times Price. ## What you have done * Created two models: `500_Data` and `100_P&L` * Connected Excel data with [DATA](/data/) * Used [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) to project values forward * Created simulatable drivers with [EXPAND](/expand/) * Calculated Revenue as Volume times Price --- # Part 5: Simulate URL: https://docs.valsight.ai/part-5-simulate/ Description: In this part, you create a workspace, set up assumptions in the Scenario Manager, and activate a simulation scenario. In this part, you create a workspace, set up assumptions in the Scenario Manager, and activate a simulation scenario. **Simulations** in Valsight start from a data baseline, apply line items to simulatable nodes, and **calculate scenarios as changes on top of that baseline**. For detailed reference on any of the concepts here, see [Workspaces](/workspaces/) and [Scenario Manager](/scenario-manager/). ## Watch the video guide Video: [Simulation](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6896648198_Simulation.mp4) ## Steps ### Create a workspace A workspace is where you analyze results and run simulations. 1. Go to the **Workspace overview** within your project. 2. Click **Add**. 3. Enter the workspace details: | Field | Value | Notes | | ---------------- | ------------------------- | ---------------------------------------- | | Name | Revenue Driver Simulation | | | Model | 100\_P\&L | Select the topmost submodel. | | Default Baseline | Data | The baseline with no assumptions active. | 4. Click **Create**. 5. Open the workspace. ### Create the price adjustment assumption The Scenario Manager is where you define assumptions and scenarios. 1. Open the **Scenario Manager**. 2. Click **Create assumption**. 3. Enter the name **Price Adjustment**. ### Add a line-item to price adjustment 1. Click the **+** icon on the assumption. 2. Select the simulatable node **Price Adjustment**. 3. Choose **Absolute**. This adds the entered value directly on top of the baseline, as opposed to **Relative**, which applies it as a percentage change. 4. Click **Create**. ### Enter a premise 1. Click on the line-item name to open the input table. 2. Enter `10` for `Premium / USA / 2026` in the **Change** column. 3. Click **Save**. ### Create the volume change assumption 1. Create a second assumption called **Volume Change**. 2. Add the simulatable node **Market Growth**. 3. Choose **Absolute**. 4. Click on the line-item name to open the input table. 5. Enter `5` for `Europe / 2026` and `3` for `America / 2026` in the **Change** column. 6. Click **Save**. ### Activate the assumptions Activate both assumptions for the **Simulation** scenario. ## What you have done * Created a workspace * Set up two assumptions in the Scenario Manager * Activated the simulation scenario --- # Part 6: Analyze Results URL: https://docs.valsight.ai/part-6-analyze-results/ Description: In this part, you create different chart types to inspect the simulation results. In this part, you create different chart types to inspect the simulation results. **Analysis** in Valsight is using charts, bridges, and tables to **compare scenarios, understand changes, and interpret model outcomes**. For detailed reference on any of the concepts here, see [Visualizing Data](/visualizing-data/). ## Watch the video guide Video: [ColumnChrt](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6896975907_ColumnChrt.mp4) ## Steps ### Create a column chart 1. Navigate back to sheet. 2. Click **Add chart**. 3. Choose **Column chart**. 4. Select **Revenue** as the measure. 5. Choose **Simulation** as the scenario. 6. **Create** the chart. 7. Open **Configure axes** and set: | Setting | Value | | ------- | ---------------------------------------------- | | X-axis | Year (default) | | Groups | Remove "Scenario" and add **Product** instead. | 8. Enable **Stacked** view using the checkbox below the chart type selector. 9. Set **Stack Totals** to **Combined sum** to show the combined revenue for both products. This control only appears once **Stacked** is on. 10. Under **Scales and Digits**, set **Scale Size** to Thousand and **Decimal Places** to 0. 11. Click **Save**. The bar chart shows Revenue by Year, stacked by Product, with totals displayed. ### Add the Scenario Manager as a chart 1. Click **Add chart** again. 2. Select **Scenario Manager**. 3. **Create** the chart. Activate or deactivate assumptions and immediately see the results update in the bar chart. ### Create a scenario bridge 1. Click **Add chart**. 2. Select **Scenario bridge**. 3. **Select node**: Revenue 4. Choose the two scenarios you want to compare. 5. Choose **Assumptions** for Comparison 6. Select the year **2029** for display. 7. **Create** the bridge. The bridge now shows how much "Price Adjustment" and "Volume Change" each contribute to the revenue difference between the data baseline and the Simulation scenario in 2029. ### Create a table 1. Click **Add chart**. 2. Select **Table**. 3. Select **Volume, Price, and Revenue** 4. Choose the **Simulation** scenario and click **Create**. 5. Set the **Aggregation** type of Price to [Weighted Average](/aggregation-settings/) in the Model Editor, and pick **Volume** as the weighting node in the same dialog. The dialog refuses to save without one. Weighted Average is offered as a display aggregation only. 6. Open **Configure axes** and set: | Setting | Value | | ------- | --------------------------------- | | Columns | Remove **Scenario**, add **Year** | 7. Under Rows click on **Sort** and place Revenue on the latest position. 8. Under Columns click on **Create Comparison** and set: | Setting | Value | | ---------------- | ----- | | Reference value | 2025 | | Comparison value | 2029 | | Type | CAGR | 9. Under **Formatting** and **Rows**, set Revenue as a **grand total** row and indent Volume and Price. 10. Click **Save**. ## What you have done * Added the Scenario Manager to the workspace * Created charts to analyze KPI development ## Summary **Congratulations!** You have built a complete Valsight project from scratch: * created a project * set up dimensions and uploaded data * built a driver model * simulated assumptions * analyzed the results ## Next steps * Add more scenarios in the [Scenario Manager](/scenario-manager/) and compare them * Experiment with [Line-Item Variants](/line-item-variants/) like Best, Realistic, and Worst * Explore the [Function catalog](/function-catalog/) for additional modeling functions * Learn more about [Structure Driver Models](/structure-driver-models/) in the Valsight documentation --- # Partner Policy URL: https://docs.valsight.ai/partner-policy/ Description: At Valsight GmbH (“Valsight”), we believe that strong, trusted partnerships are essential to shared success. ## 1. Introduction At **Valsight GmbH** (“**Valsight**”), we believe that strong, trusted partnerships are essential to shared success. This Partner Policy outlines our expectations for collaboration with our business partners, suppliers, and service providers. Our goal is to maintain long-term, transparent, and responsible relationships that support our customers, employees, and partners alike. ## 2. Partnership principles We expect all partners to uphold the same standards of professionalism, ethics, and compliance that we apply within Valsight. Partnerships with Valsight are founded on the following principles: * **Integrity:** Conduct business fairly, honestly, and transparently. * **Compliance:** Follow all applicable laws, regulations, and contractual obligations. * **Respect:** Treat employees, customers, and other partners with dignity, fairness, and professionalism. * **Confidentiality:** Protect any sensitive or proprietary information shared by Valsight or its customers. * **Sustainability:** Act responsibly with regard to environmental and social impacts. ## 3. Information security requirements Valsight is committed to protecting information assets and expects the same from its partners. To ensure the confidentiality, integrity, and availability of information, partners must adhere to the following security standards: * Maintain an appropriate **Information Security Management System (ISMS)** or equivalent security framework. * Use **up-to-date antivirus and endpoint protection software** on all systems accessing or processing Valsight information. * Keep all systems and software **regularly updated** with security patches. * Ensure that **access controls** are in place, including strong authentication and least-privilege principles. * Encrypt sensitive information during transmission and storage where applicable. * Restrict access to Valsight data to authorized personnel only. * Report any **security incident, data breach, or suspected compromise** to Valsight **immediately** (within 24 hours of detection). * Dispose of confidential information securely and in accordance with applicable data protection laws. Valsight may request evidence of compliance (e.g., security certifications, process documentation) as part of partner onboarding or periodic reviews. ## 4. Data protection Partners who process personal or confidential information on behalf of Valsight must comply with the **EU General Data Protection Regulation (GDPR)** and any other applicable privacy laws. This includes ensuring that: * Personal data is processed only for the agreed business purpose. * Subcontractors (if used) follow equivalent data protection and security requirements. * Data is deleted or returned to Valsight upon request or contract termination. ## 5. Communication and collaboration Valsight values open and constructive communication with partners. Partners are expected to: * Keep Valsight informed about relevant developments, risks, or incidents. * Work collaboratively to address issues or process improvements. * Share innovations and best practices that contribute to mutual success. ## 6. Compliance and audits Valsight reserves the right to verify partner compliance with this policy, including through documentation requests or audits. Partners are expected to cooperate in such reviews and to promptly address any findings or recommendations. ## 7. Non-Compliance If a partner fails to meet the obligations defined in this policy or in the corresponding agreements, Valsight may: * Request corrective actions, * Temporarily suspend collaboration, or * Terminate the partnership agreement. Repeated or serious violations may result in permanent exclusion from future cooperation. ## 8. Continuous improvement Valsight encourages continuous improvement and welcomes partner feedback on how to enhance collaboration, security, and compliance processes. ## 9. Contact For any questions regarding this Partner Policy or information security requirements, please contact: **Valsight GmbH** 📧 [**support@valsight.com**](mailto\:support@valsight.com) 🌐 [**www.valsight.com**](https://www.valsight.com) --- # Performance Flags URL: https://docs.valsight.ai/performance-flags/ Description: Config Option Setting Effect Recommendation for 8GB / 4 core VM | Config Option | Setting | Effect | Recommendation for 8GB / 4 core VM | | ------------------------------------------------------------ | ------------------------------------------- | -------------------------------- | ----------------------------------------------------------------- | | conf/environment.sh (copy from conf/environment.sh.default) | -Xms, -Xmx | Initial and max heap size of JVM | 4 GB (50% of available memory if Postgresql is on the same host) | | System Config Page, Features | cache.maxConfiguredCubes | Max simulation cubes in RAM | 10000 | | | featureFlags.asyncQueryExecutorCorePoolSize | Max parallel simulations | 4 (number of cores) | --- # Perspective Selector URL: https://docs.valsight.ai/perspective-selector/ Description: The Perspective Selector is a new interactive chart type introduced for enhancing presentations in Valsight. Its primary purpose is to enable decision-makers… The **Perspective Selector** is a new interactive chart type introduced for enhancing presentations in Valsight. Its primary purpose is to enable decision-makers and presenters to apply predefined filters across sheets in a visually appealing, intuitive way, without switching to edit mode or accessing complex filter configurations. ## Why it matters * **Seamless Presentation Mode**: Quickly adjust views during discussions. * **No Technical Know-How Required**: Apply complex filters via a single click. * **Visual Storytelling**: Each perspective can include images and tailored filter sets. This functionality significantly simplifies scenario exploration and data storytelling during live meetings. ![Perspective Selector Valsight.png](./images/6125027370.png) ## Navigating to the feature ### 1. Creating a Perspective Selector > **Prerequisite:** an administrator must switch on the global setting `featureFlags.use.perspectives`. It is off by default, so until it is enabled the **Perspective Selector** chart type does not appear under **Others** in the chart wizard. 1. **Open a Sheet** within your workspace. 2. Click on **“+ Chart”** to open the chart wizard. 3. Under the **“Others”** section, find and select the **“Perspective Selector”** chart type. ### 2. Configuring each perspective A Perspective consists of a “**Name**”, an “**Image**” and a “**Filter Selection**”. All properties are optional and can be configured in every combination. * **Perspective Name**: The name will be shown in the perspective tile. If you upload an additional image the name will be shown as a tooltip. * **Add Image (optional)**: * Upload PNG/JPG (max 2.5MB, max width 1920px). * If no image is provided, the name will be shown in the tile. * **Add Filters**: * Select filter dimensions and values. * A perspective cannot hold a filter with **all** values of a level selected: that is rejected with ‘Perspectives do not support filters where all level values are selected. Please adjust or remove the filter.’ Deselect at least one value, or remove the filter. A filter with **no** values selected is refused as well. * Use the **“Manage filters”** button to edit filters. * Applied filters are shown as tags in the dialog. ### 3. Interacting with the tile Once created: * Each draggable tab appears as a clickable button on the tile. * Clicking a button applies the associated filter set. This needs **edit rights on the workspace**: a read-only viewer cannot switch perspective at all. * The tile header shows **Edit** and **Settings (⚙️)** icons on hover. * Via the cogwheel: * Rename the tile via **“Edit title”**. * The tile can also be: * Moved * Duplicated * Saved as a template (like other charts) ## Managing & customizing ### Admin/User rights * **No per-user customization**: Perspectives are shared and synced across users. Switching perspective is a change to the workspace, not a personal view, so it changes what **every** other user of that workspace sees. * **Switching needs edit rights.** Someone with read-only access to the workspace cannot click a perspective button, which matters when a presentation is opened by an audience rather than by its author. * **Edits in configuration dialogs** are locked while someone is editing to avoid conflicts. A perspective switch made while another user holds that lock does not go through. ### Tile customization * Perspectives tile supports standard layout behaviors: * Can be rearranged and resized. * The layout follows the tile's shape on its own: resize it wider than it is tall and the perspectives lay out in a row, taller than wide and they stack in a column. There is nothing to configure. The tile scrolls, in either direction, when they do not fit. * Combining multiple perspective tiles to impact a worksheet is also possible. ### Filter behavior * **Perspective Filters Logic**: * **Within one perspective**: **INTERSECTION**. Filters on different levels are combined, so only data matching all of them is shown. Within a single level, the values you select are combined as a union. * **Across perspectives**: **UNION** per level. Each tile button toggles independently, so several perspectives can be active at the same time, and every active perspective on the sheet contributes its values. * **Combined with worksheet and chart filters**: **INTERSECTION**. * **No changes to**: * Sheet-level filters * Filter conflict detection * Chart subtitles (Perspective filters won’t appear here) > Perspectives are limited by the applied workspace filters, worksheet filters and chart filters. ### Limitations * In presentation mode, Perspective Selectors are shown but **read-only**. The tiles display the perspective that was active when the presentation was captured, and clicking a tile does not change the filter. * This feature requires **CORPORATE** or **ENTERPRISE** licenses. ## Example use case Imagine a boardroom slide where different departments (Sales, Marketing, Finance) need custom views. With the Perspective Selector: * Each department has a pre-defined button. * During the meeting, click a button to instantly shift the view to that department’s filters. * Presentations stay clean, contextual, and responsive without edit interruptions. --- # PM URL: https://docs.valsight.ai/pm/ Description: Shifts the input node one month into the future while retaining all other dimensions. Use this when you need last month's values alongside current data for month-over-month comparisons. **Category:** [Compare periods](/compare-periods/) ## Overview The **PM** function **shifts the input node one month into the future** while retaining all other dimensions. Use this function when you need last month's values alongside current data for month-over-month comparisons. ## Syntax `PM('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | -------------------------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node that is shifted, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | ## Watch out * This function is only available on projects that use the **month time dimension**. A project has either Year, Quarter, Month and Day or Iso-Year, Week and Day, never both, so on a week-dimension project the node fails with an error saying the Month level could not be found. The time dimension is chosen per project, see [Project Settings](/project-settings/). ## Examples ### Shifting values by one month Each value appears one month later in the result. **Input node:** `'Profit'` | Month | Value | | ------- | ----- | | 2025-01 | 35 | | 2025-02 | 42 | | 2025-03 | 47 | **Formula:** `PM('Profit')` | Month | PM Result | | ------- | --------- | | 2025-02 | 35 | | 2025-03 | 42 | | 2025-04 | 47 | ### Shifting values by two months (nested PM) Nesting PM calls shifts values further into the future. Here, each value moves two months forward. Try [SHIFT](/shift/) as an alternative with a custom offset. **Input node:** `'Profit'` | Month | Value | | ------- | ----- | | 2025-01 | 35 | | 2025-02 | 42 | | 2025-03 | 47 | **Formula:** `PM(PM('Profit'))` | Month | PM Result | | ------- | --------- | | 2025-03 | 35 | | 2025-04 | 42 | | 2025-05 | 47 | ## Related | Function | When to use instead | | --------------------- | ----------------------------------------------------------------------------------------- | | [PQ](/pq/) | When you need the previous quarter instead of the previous month. | | [SHIFT](/shift/) | When you need a custom offset or want to shift along a specific time level. | | [MOM\_ABS](/mom-abs/) | When you need the absolute difference to the previous month, not just the shifted values. | --- # PMT URL: https://docs.valsight.ai/pmt/ Description: Calculates the periodic payment required for a recurring investment, given an interest rate, number of periods, and present value. **Category:** [Finance functions](/finance-functions/) ## Overview The **PMT** function **calculates the periodic payment required** for a recurring investment based on a constant interest rate, a number of recurring payments, a present value, and either ordinary annuity or annuity due (`Type`) indicating whether payments are due at the beginning or the end of the period. Use this function when the rate, duration, and present value are known and you want to calculate the periodic payment. ## Syntax `PMT('Rate', 'Nper', 'Pv' [, 'Fv' [, Type]])` ## Parameters | Parameter | Description | Type | Required | Default | | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | ------- | | **Rate** | The interest rate. | Node reference | Yes | -- | | **Nper** | Number of periods: the number of payments to be made. | Node reference | Yes | -- | | **Pv** | Present value: the current value of the annuity. | Node reference | Yes | -- | | **Fv** | Future value remaining after the final payment has been made. | Node reference | No | `0` | | **Type** | Indicates when payments are due (`1` = payment at beginning of period / annuity due, `0` = payment at end of period / ordinary annuity). Must be written as a plain number, not in quotes and not as a node reference. | Number | No | `0` | ## Watch out * `'Pv'` is the leading input node: its levels define the result's shape, and every other input is aligned to it. * Every other input may use only levels that also exist on `'Pv'`. It may use fewer levels, but not a level that `'Pv'` does not have. * On the levels it shares with `'Pv'`, each input must cover the same level values, otherwise the rows do not line up and the function returns an error. * Each input can also be a single number. * Giving every input the same levels as `'Pv'` skips an internal alignment step and improves performance. ## Examples ### Calculate a periodic payment This example shows a standard annuity setup with a fixed interest rate, a fixed duration, and a present value. It returns the periodic payment required for the investment setup. | Parameter | Value | | ------------------------------------------------------------------------------------------------------------- | ----- | | `Rate` (Interest Rate) | 0.03 | | `Nper` (Number of Periods) | 24 | | `Pv` (Present value) | 6000 | | `Fv` (Future value) | 0 | | `Type`
Payment at Beginning of Period (Annuity Due) = 1
Payment at End of Period (Ordinary Annuity) = 0 | 0 | **Formula:** `PMT('Rate', 'Nper', 'Pv', 'Fv', 0)` | PMT Result | | ---------- | | -354.28 | The result is negative because it is marked as a payment. ## Related | Function | When to use instead | | ---------- | --------------------------------------------------------------------------------------------------- | | [PV](/pv/) | When you want the present value of an annuity-style payment stream instead of the periodic payment. | | [FV](/fv/) | When you want the future value of an annuity-style payment stream instead of the periodic payment. | --- # POWER URL: https://docs.valsight.ai/power/ Description: Raises values from the first input to the power of the second, using the first as the base and the second as the exponent. Both inputs can be numbers or node references. **Category:** [Math & numeric](/math-numeric/) ## Overview The **POWER** function **returns the power of the values, using the first input as the base and the second as the exponent**. Both inputs can be numbers as well as nodes. Use this function when you need to raise a node or numeric value to a fixed or row-wise exponent. ## Syntax `POWER('Node1' | value, 'Node2' | value)` ## Parameters | Parameter | Description | Type | Required | | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- | | **Base** (`Node1 \| value`) | The value that will be multiplied by itself, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference or number | Yes | | **Exponent** (`Node2 \| value`) | The number of times the base will be multiplied by itself. Can also be a number or a fraction, for example `1/3` to calculate a third root. | Node reference or number | Yes | ## Watch out Three combinations are mathematically undefined and make the whole calculation fail, not just the affected row: * A base of **0 with a negative exponent**, and `0` raised to `0`. * A **negative base with a fractional exponent**. This is exactly the third-root case above: `POWER('Node', 1/3)` fails as soon as one row of the node is negative. Guard the base with `MAX('Node', 0)` or [ABS](/abs/) if negatives are possible. * A result **too large to represent**, which happens quickly with a large base and a large exponent. ## Examples ### Raising one node to the power of another This example shows POWER applied row-wise using node A as the base and node B as the exponent. Here the exponent is constant at 2, so the result squares each base value. **Input node:** `'Base'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 3 | | 2027 | 4.5 | **Input node:** `'Exponent'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 2 | | 2027 | 2 | **Formula:** `POWER('Base', 'Exponent')` | Year | POWER Result | | ---- | ------------ | | 2025 | 4 | | 2026 | 9 | | 2027 | 20.25 | ## Related | Function | When to use instead | | -------------- | ----------------------------------------------------------------------------------------- | | [SQRT](/sqrt/) | When you only need the square root of a single input instead of a general exponentiation. | | [EXP](/exp/) | When you need exponentiation with the fixed base e instead of a custom base and exponent. | --- # PQ URL: https://docs.valsight.ai/pq/ Description: Shifts the input node one quarter into the future while retaining all other dimensions. Use this when you need last quarter's values alongside current data for quarter-over-quarter comparisons. **Category:** [Compare periods](/compare-periods/) ## Overview The **PQ** function **shifts the input node one quarter into the future** while retaining all other dimensions. Use this function when you need last quarter's values alongside current data for quarter-over-quarter comparisons. ## Syntax `PQ('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | -------------------------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node that is shifted, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | ## Watch out * This function is only available on projects that use the **month time dimension**. A project has either Year, Quarter, Month and Day or Iso-Year, Week and Day, never both, so on a week-dimension project the node fails with an error saying the Quarter level could not be found. The time dimension is chosen per project, see [Project Settings](/project-settings/). ## Examples ### Shifting values by one quarter Each value appears one quarter later in the result. **Input node:** `'Profit'` | Quarter | Value | | ------- | ----- | | 2025-Q1 | 35 | | 2025-Q2 | 42 | | 2025-Q3 | 47 | **Formula:** `PQ('Profit')` | Quarter | PQ Result | | ------- | --------- | | 2025-Q2 | 35 | | 2025-Q3 | 42 | | 2025-Q4 | 47 | ### Shifting values by two quarters (nested PQ) Nesting PQ calls shifts values further into the future. Here, each value moves two quarters forward. Try [SHIFT](/shift/) as an alternative with a custom offset. **Input node:** `'Profit'` | Quarter | Value | | ------- | ----- | | 2025-Q1 | 35 | | 2025-Q2 | 42 | | 2025-Q3 | 47 | **Formula:** `PQ(PQ('Profit'))` | Quarter | PQ Result | | ------- | --------- | | 2025-Q3 | 35 | | 2025-Q4 | 42 | | 2026-Q1 | 47 | ## Related | Function | When to use instead | | --------------------- | ------------------------------------------------------------------------------------------- | | [PY](/py/) | When you need the previous year instead of the previous quarter. | | [SHIFT](/shift/) | When you need a custom offset or want to shift along a specific time level. | | [QOQ\_ABS](/qoq-abs/) | When you need the absolute difference to the previous quarter, not just the shifted values. | --- # Presentation Favorites Headline URL: https://docs.valsight.ai/presentation-favorites-headline/ Description: The header of the "Show all favorites" page can be customized. The header of the "Show all favorites" page can be customized. ![2018-03-01 10-15-04.png](./images/5094190182.png) Similar to the steps at [Add a copyright or confidentiality notice](/add-a-copyright-or-confidentiality-notice/), edit the field **featureFlags.workspaceSnapshotFavoritesTitle** in the project settings. --- # PREVIOUS URL: https://docs.valsight.ai/previous/ Description: The PREVIOUS function returns the previous period value of a node with a defined base case, enabling loop-style calculations along the time dimension. **Category:** [Rollforward & time series](/rollforward-time-series/) > The previous function is almost never necessary and has **considerable performance and usability disadvantages** over the [ROLLFORWARD](/rollforward/) function. Its usage is not advised, unless you absolutely must - contact the Valsight support for information on your specific problem to evaluate if it can be modelled with a ROLLFORWARD instead. ## Overview The **PREVIOUS** function **returns the previous period value of a node, except for the base period where it returns the value of the base node**. All effects applied between the node and the base node therefore cumulate over the year. The function can be used to create models where the value of a node depends on the result for the previous period of a node higher in the value driver tree, thereby creating a loop that is resolved along the time dimension. An example is provided below, where the `'Base Cost'` node depends on the final `'Cost'` of the previous year, calculating the costs based on the costs of the previous year with the two drivers inflation and productivity. Use this function when you need loop-style logic with a defined base case rather than a simple previous-period comparison. ## Syntax `PREVIOUS('Node', "Level", 'BaseNode', "BaseValue")` ## Parameters | Parameter | Description | Type | Required | | ------------- | ---------------------------------------------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node of which the previous period value is taken, for example `'Cost'`. | Node reference | Yes | | **Level** | The time level that defines the previous value, for example `"Year"` where the previous of `"2026"` is `"2025"`. | Level name | Yes | | **BaseNode** | Input node that is used to get the value of the node for the base period, for example `'Initial Cost'`. | Node reference | Yes | | **BaseValue** | The value describing the base period, for example `"2025"`. | Level value | Yes | ## Watch out When using the PREVIOUS function, the following limitations apply to all nodes between `'Node'` and `'BaseNode'`: * No manipulation of time, for example by using `SHIFT`. * All nodes must have the time level used for the loop. * `'Node'` and `'BaseNode'` must have the same levels. ## Examples ### Loop logic with an explicit base period This example shows how PREVIOUS creates a loop along the time dimension by taking the prior year's result and using a fixed base period to start the calculation. **Input node:** `'Initial Cost'` | Year | Cost | | ---- | ---- | | 2025 | 100 | **Input node:** `'Productivity Change'` | Year | Productivity Change | | ---- | ------------------- | | 2025 | 0% | | 2026 | 20% | | 2027 | 20% | | 2028 | 20% | **Input node:** `'Cost Inflation'` | Year | Cost Inflation | | ---- | -------------- | | 2025 | 0% | | 2026 | 10% | | 2027 | 10% | | 2028 | 10% | **Formula:** `PREVIOUS('Cost', "Year", 'Initial Cost', "2025")` | Year | PREVIOUS Result | | ---- | --------------- | | 2025 | 100 | | 2026 | 100 | | 2027 | 130 | | 2028 | 169 | **Formula:** `'Base Cost' * (EXPAND(1, "Year") + 'Cost Inflation' + 'Productivity Change')` | Year | Cost | | ---- | ----- | | 2025 | 100 | | 2026 | 130 | | 2027 | 169 | | 2028 | 219.7 | ## Related | Function | When to use instead | | ---------------------------- | --------------------------------------------------------------------------------------------------------------------- | | [ROLLFORWARD](/rollforward/) | When the same logic should be modelled in a more modern and performant way instead of relying on PREVIOUS loop logic. | | [PY](/py/) | When you only need a simple previous-year reference instead of loop-style logic with an explicit base case. | --- # Project Rights URL: https://docs.valsight.ai/project-rights/ Description: On this page, we will show you how to edit and manage project permissions in Valsight. As an example we want to grant a user "test.user" the right to work on… On this page, we will show you how to edit and manage project permissions in Valsight. As an example we want to grant a user "test.user" the right to work on the project "50 Sky Automotive" in a model and a workspace. For more details on the effects of permissions, read the documentation page on [Access Rights](/access-rights/). ## Edit and manage project permissions ### Select the project To get started, select the menu entry "Configuration". Now select the project that you want to change permissions for from the list on the left (We will select "50 Sky Automotive"). Then select "Security". ![Screenshot 2020-02-04 at 11.00.25.png](./images/5094192608.png) ### Modifying project rights After selecting "Security" you will be forwarded to the security settings page. Select "Access Report" next to “Project Access” to get an overview of the users and their access to the project. ![security settings v2.16.png](./images/5094212214.png) Click "Edit" to change the permissions for the project. ![Screenshot 2020-02-05 at 09.13.07.png](./images/5094192723.png) To work within a project our user needs at least "Can use" permissions on the project. Give the user the appropriate permissions and save the changes. ![Screenshot 2020-02-05 at 09.17.13.png](./images/5094192718.png) Now you have become acquainted with one way to edit permissions on a project ("Configuration" > "Security" > "Access Report"). But there is another one ("Configuration" > "Access control") which also lets you also change permissions on workspaces and models. ### Grant permissions for specific models or workspaces In order to change models and use the workspaces, our user needs to be granted permission for these as well. To do so navigate to "Configuration" → "Access control". Select the project containing the model and workspace from the dropdown. Then tick "models" and "workspaces" and click "Show". You will see an overview of all models and workspaces in the selected project. Select "Edit" on the model and grant the user "Can edit" permissions on the model. Do the same with the workspace and grant the user "Full Access" permissions. You can find a detailed explanation of the different access rights on the documentation page about [Access Rights](/access-rights/). ## Getting a transparent overview over user type restrictions **Ability:** The feature of two added rows in the 'Rights explanation' gives you the ability to easily check the user type restrictions for every single user of all projects. **Example:** you need a quick and transparent overview of the access rights of a certain user for specific projects ### Open the access control page Open the access control page via setting > access rights and check all information you need to see ### Click a user and project cell When hovering over a cell of a user and a project you need the information on, your cursor will display a small ‘?’ next to it. To access the overview, click on a cell. ![image2020-11-24\_9-56-4.png](./images/5094193885.png) ### Read the rights explanation After clicking on it, a pop-up window opens. The added feature relates to the upper two rows (see picture). ![image2020-11-24\_9-57-13.png](./images/5094194153.png) In this case, you checked the access rights of an unrestricted user type (test.user1) with admin rights in the project ALPHA. That user has an enabled user type “Use” and an enabled user type “Admin”. In another case, you need to check the access rights of for example a Basic user (test.user2) in project ALPHA. ![image2020-11-24\_9-58-37.png](./images/5094194158.png) After clicking on the cell for that user and the related project the pop-up window opens. ![image2020-11-24\_10-0-6.png](./images/5094194058.png) You now see that the analyst has an enabled user type “Use” but is not listed as a user type “Admin”. --- # Project Settings URL: https://docs.valsight.ai/project-settings/ Description: The settings of projects can be accessed via the navigation bar settings (admin UI) and then selecting projects or directly from the project overview page. The settings of projects can be accessed via the navigation bar settings (admin UI) and then selecting projects or directly from the project overview page. Accessing the settings via the admin UI brings you to more advanced options for your project. Via the **project overview page,** you can access the **basic settings** of your project. This is the **focus of this page**. To get there click on the **three-dot** menu in the lower right corner of the **project card**. In the first step of the settings, you can either open the project, upload an image for your project, or advance to the general settings of your project. In the general settings of your project, you can adjust the **project name**, the **business key**, the **project description** and also change the **time settings** of your project. ## Navigating to Project Settings * First, head over to the project list view\*\*.\*\* * Click the **three-dots button** to see the available actions on the selected project ![pSettings.png](./images/5094193425.png) ## Project image upload By clicking "Upload Image", the image upload wizard will be prompted, through which you'll be able to upload an image from your computer and assign it to the project. The image must be a PNG or a JPEG. The same wizard is used for the Upload Image action on the model list, the workspace list and the workflow overview, so the same rule applies there. ![imageUploadWizard.png](./images/5094193340.png) ## General Project Settings In the general project settings, you can adjust the name, business key, and description of your project. ### Business Key A business key is used as a unique project identifier. As projects can have the same name, a business key is used to differentiate, find or assign projects no matter the name given. There are a few restrictions on the style of the business key. The notation may only contain upper case letters, numbers, and underscores as it can be used in programmatic access to the project. When using lower case letters for your business key, those will automatically be transformed into upper case letters when pressing "Next". ![image2021-3-24\_11-28-16.png](./images/5094216051.png) ## Project time settings The time settings of projects are divided into three categories: “Horizon Period”, “Horizon” and “Current Period”. All three options can be changed in the project settings. ![Screen Shot 2020-05-27 at 19.21.58.png](./images/5094193655.png) ### Horizon Period The horizon period describes the granularity you want to analyze your data with. That can be done in years, quarters, months, or weeks. Weeks are available on projects using the ISO 8601 calendar, see the Limitations section below. ### (time) Horizon The time horizon describes the amount of time you want to plan ahead for your project. You can choose a starting and an end date for that. This option can be set in years and months. ### Current period The current period describes the point in time you want to start your project at. ### Divide years into After configuring these settings, you can now decide which standards your calendar should follow. The two options provided are the gregorian calendar and the ISO 8601. The gregorian calendar is split up into years, quarters, months, and days. ISO 8601 is split up into years, weeks, and days. > **Switching between the two rebuilds the Time dimension.** Moving to ISO 8601 deletes the Quarter and Month levels and unlinks the CalendarMonth dimension; moving back deletes the Week level. Either direction also clears the horizon overrides on every model and workspace in the project, so any model running on its own horizon reverts to the project's. The switch is refused outright if one of your own dimensions already holds a level named after one the switch has to create, see [Best Practices for Dimensions](/best-practices-for-dimensions/). ### System managed calendar months Calendar months are an optional dimension that you can enable in the project settings. This will generate a “CalendarMonth” dimension holding a single level, also called **CalendarMonth**, whose twelve values are 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12. The CalendarMonth dimension can be used to analyze **seasonality effects** in your business (e.g. profits per month and year for a skiing region). The difference between calendar months and the regular [month Dimension](/calendar-months-dimension/) is that calendar month does not contain the year, so you can compare the profits from a specific month over the years. Upon ticking the checkbox and clicking the confirm button, a new **dimension** named ‘CalendarMonth’ will be automatically generated. This dimension contains the calendar months and will be linked with the **“Month” Level** in the **“Time” Dimension**. ![image2022-2-17\_16-20-58.png](./images/5094231160.png)![image2021-3-25\_17-20-57.png](./images/5094216066.png) #### Chart example using calendar months ![image2022-2-22\_15-25-12.png](./images/5094230880.png) #### Disabling calendar months When disabling the setting "System managed Calendar Months", the system will no longer automatically manage the dimension for you. However, it will not automatically delete the calendar month dimension (as this might lead to data loss). If required, the dimension can be deleted manually using the dimension management. In order to re-enable calendar months, you have to delete the calendar month dimension using the dimension management. > **Time Horizon in Model and Workspace** > > How to change the time horizon for models can be found [here](/changing-the-time-horizon/). > > Changing the time horizon for Workspaces is further explained [here](/workspaces/). ### Limitations When using the week-based time dimension: * Horizons on months cannot be combined with a week-based time dimension * Horizons on years might not match full ISO weeks * System managed calendar months are not supported in combination with weeks * Nodes on weeks with aggregation types CLOSINGSUM or CLOSINGAVG cannot include the SHIFT function in operations * Shifting on line items in workspace is only supported on months * The following functions do not support input with weeks: SCHEDULE\_PROJECTS, DEPRECIATION --- # Project Variables URL: https://docs.valsight.ai/project-variables/ Description: Project variables let you define shared values once, for time, data sources, or any other shared input, and reuse them across models and scenarios. They ke… Project variables let you define shared values once, for time, data sources, or any other shared input, and reuse them across models and scenarios. They keep models consistent, flexible, and easy to maintain. ## When to use it * When node operations depend on values that may change over time (e.g. project start year, a shared growth rate) * When the same value is referenced across multiple nodes and must stay synchronised * When you want scenarios to use different variable values without rebuilding the model ## How it works Project variables act as **central placeholders for values**. They can be defined at the project level, used inside node calculations, and overwritten per scenario when needed. There are two types: * **System variables**: predefined by Valsight and derived from project settings (e.g. `$PROJECT_HORIZON_START`). Shown in blue; configured via project settings only. * **Custom variables**: created and named by users with values they define. Variables can hold numeric or non-numeric values. Changing a variable's value in one place automatically updates all calculations that rely on it. ![Configure Project Variables.png](./images/6663405575.png) ## Creating a variable Custom variables are created in **Project Settings > Configure Variables > Configure Variables Overview**. ![Projects settings.png](./images/6880002051.png) > **Naming restrictions** > > The first character must be a letter. The remaining characters can be letters (upper or lowercase), numbers, underscores, or dashes. Video: [Add variable](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6880854018_Add-variable.mov) ## Dynamic project variables Custom variables can be either **fixed** or **dynamic**: * **Fixed**: you enter the value directly. This is the default, and how all existing variables behave. * **Dynamic**: the value is calculated from a formula that references other fixed variables. When a referenced value changes, the dynamic variable updates automatically. Use a dynamic variable when one value should always be derived from another rather than maintained by hand: for example, a forecast end that is always 12 months after the forecast start. When you add a variable, choose its **type**. For a dynamic variable, define the calculation in the formula editor, which provides syntax highlighting and autocomplete for two time functions: * [DATE\_OFFSET](/date-offset/): offsets a time level value forward or backward by a number of years, quarters, months, weeks, or days. * [DATE\_EXTRACT](/date-extract/): extracts the year, quarter, month, week, or day from a time level value. **Example.** With a fixed variable `$FORECAST_START = "2026-04"`, define a dynamic variable `FORECAST_END` as: **Formula:** `DATE_OFFSET("$FORECAST_START", "Month", 12)` | TimeLevelValue | → FORECAST\_END | | -------------- | --------------- | | `"2026-04"` | `"2027-04"` | The variable overview shows each variable's **type** and its **resulting value**. If a formula is invalid, the value shows an error state; you can still save the variable and correct the formula later. ## How dynamic variables behave * Dynamic variables can reference **fixed** variables only, not other dynamic variables. * Only fixed variables can be overwritten in a scenario. Dynamic variables are read-only in the Scenario Manager. * A fixed variable can be deleted even while a dynamic variable uses it. Deleting it invalidates any dynamic formula that referenced it. ## Available system variables System variables are available in every project. They are listed on the variable overview alongside your own, tagged **Pre-defined**. Most of them are read-only there and follow project settings, under Time Settings. ![System variables\_time settings.png](./images/6881214465.png) | Where it is set | Variable | Value | Example Value | | ------------------------------- | ------------------------ | ------------------------------------------------ | ------------- | | Project settings, Time Settings | `$PROJECT_HORIZON_LEVEL` | The project's horizon period from time settings. | "Year" | | Project settings, Time Settings | `$PROJECT_HORIZON_START` | The start value of the project time horizon. | "2025" | | Project settings, Time Settings | `$PROJECT_HORIZON_END` | The end value of the project time horizon. | "2030" | | Variable overview | `$CURRENT_PERIOD` | The current period of your project. | "2026" | | Variable overview | `$CUSTOM_VARIABLE` | User-defined value. | | `$CURRENT_PERIOD` is the exception among the pre-defined variables: it is editable, and it is not a Time Setting. There is no **Current period** control in project settings. Change it on the variable overview like any other variable. ## Limitations * Sharing scenarios with overwritten variables is not supported. * Variable names must follow naming rules to be usable in formulas. * The project horizon variables are managed through project settings and cannot be edited on the variable overview. ## FAQ **Why should I use project variables instead of fixed values?** They make models easier to maintain by centralizing key value management. **Can variables be different per scenario?** Yes. Fixed variables can be overwritten at the scenario level. Dynamic variables are read-only in scenarios and always follow their formula. **What happens if a project variable changes?** All calculations using that variable update automatically, unless a scenario has pinned its own value. Any dynamic variables that reference it are recalculated too. **Are all variables visible in the same place?** Yes. The variable overview lists every variable in the project, custom and pre-defined alike. The pre-defined ones carry a **Pre-defined** tag, and the project horizon variables are shown there read-only because they follow project settings. ## Related * [Nodes](/nodes/) * [Working with different Model Baselines](/working-with-different-model-baselines/) * [Using Project Variables in Node Formulas](/using-project-variables-in-node-formulas/) * [Overwriting Scenario Variables](/overwriting-project-variables/) --- # Projects URL: https://docs.valsight.ai/projects/ Description: Projects in Valsight are the top-level containers that bundle together dimensions, data sources, models, workspaces, and scenarios for a specific planning us… **Projects** in Valsight are the **top-level containers** that bundle together dimensions, data sources, models, workspaces, and scenarios for a specific planning use case. ![image-20260416-104812.png](./images/7008452645.png) --- # Projektverzögerung URL: https://docs.valsight.ai/projektverzoegerung/ Description: Projektverzögerung [Projektverzögerung.pdf](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989826593_Projektverzoegerung.pdf) --- # PV URL: https://docs.valsight.ai/pv/ Description: Calculates the present value of a recurring investment, given an interest rate, number of periods, and periodic payment. **Category:** [Finance functions](/finance-functions/) ## Overview The **PV** function **calculates the present value of a recurring investment** based on a constant interest rate, a number of recurring payments, a payment per period, and either ordinary annuity or annuity due (`Type`) indicating whether payments are due at the beginning or the end of the period. Use this function when the rate, duration, and payment are known and you want to calculate the present value of an annuity-style payment stream. ## Syntax `PV('Rate', 'Nper', 'Pmt' [, 'Fv' [, Type]])` ## Parameters | Parameter | Description | Type | Required | Default | | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | ------- | | **Rate** | The interest rate. | Node reference | Yes | -- | | **Nper** | Number of periods: the number of payments to be made. | Node reference | Yes | -- | | **Pmt** | Payment per period: the amount of each payment made. Payments/costs should ideally be entered as a negative number, for example `-500`, but this is not required. | Node reference | Yes | -- | | **Fv** | Future value remaining after the final payment has been made. | Node reference | No | `0` | | **Type** | Indicates when payments are due (`1` = payment at beginning of period / annuity due, `0` = payment at end of period / ordinary annuity). Must be written as a plain number, not in quotes and not as a node reference. | Number | No | `0` | ## Watch out * `'Pmt'` is the leading input node: its levels define the result's shape, and every other input is aligned to it. * Every other input may use only levels that also exist on `'Pmt'`. It may use fewer levels, but not a level that `'Pmt'` does not have. * On the levels it shares with `'Pmt'`, each input must cover the same level values, otherwise the rows do not line up and the function returns an error. * Each input can also be a single number. * Giving every input the same levels as `'Pmt'` skips an internal alignment step and improves performance. * If costs or payments are entered as positive numbers in your model, multiply the result by `(-1)`. ## Examples ### Calculate the present value of an annuity This example shows a standard annuity setup with a fixed interest rate, a fixed duration, and a periodic payment. It returns the present value implied by the payment stream. | Parameter | Value | | ------------------------------------------------------------------------------------------------------------- | ----- | | `Rate` (Interest Rate) | 0.03 | | `Nper` (Number of Periods) | 5 | | `Pmt` (Payment per Period) | -500 | | `Fv` (Future Value) | 0 | | `Type`
Payment at Beginning of Period (Annuity Due) = 1
Payment at End of Period (Ordinary Annuity) = 0 | 0 | **Formula:** `PV('Rate', 'Nper', 'Pmt', 'Fv', 0)` | PV Result | | --------- | | 2,289.85 | ## Related | Function | When to use instead | | ------------ | ----------------------------------------------------------------------------------------------------------------------------- | | [NPV](/npv/) | When you want to discount a cash flow series into a single net present value instead of using an annuity-style payment setup. | | [FV](/fv/) | When you want the future value of an annuity-style payment setup instead of the present value. | --- # PW URL: https://docs.valsight.ai/pw/ Description: Shifts the input node one week into the future while retaining all other dimensions. Use this when you need last week's values alongside current data for week-over-week comparisons. **Category:** [Compare periods](/compare-periods/) ## Overview The **PW** function **shifts the input node one week into the future** while retaining all other dimensions. Use this function when you need last week's values alongside current data for week-over-week comparisons. ## Syntax `PW('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | -------------------------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node that is shifted, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | ## Watch out * This function is only available on projects that use the **week time dimension**. A project has either Year, Quarter, Month and Day or Iso-Year, Week and Day, never both, so on a month-dimension project the node fails with an error saying the Week level could not be found. The time dimension is chosen per project, see [Project Settings](/project-settings/). ## Examples ### Shifting values by one week Each value appears one week later in the result. **Input node:** `'Profit'` | Week | Value | | -------- | ----- | | 2025-W01 | 35 | | 2025-W02 | 42 | | 2025-W03 | 47 | **Formula:** `PW('Profit')` | Week | PW Result | | -------- | --------- | | 2025-W02 | 35 | | 2025-W03 | 42 | | 2025-W04 | 47 | ### Shifting values by two weeks (nested PW) Nesting PW calls shifts values further into the future. Here, each value moves two weeks forward. Try [SHIFT](/shift/) as an alternative with a custom offset. **Input node:** `'Profit'` | Week | Value | | -------- | ----- | | 2025-W01 | 38 | | 2025-W02 | 45 | | 2025-W03 | 52 | **Formula:** `PW(PW('Profit'))` | Week | PW Result | | -------- | --------- | | 2025-W03 | 38 | | 2025-W04 | 45 | | 2025-W05 | 52 | ## Related | Function | When to use instead | | --------------------- | ---------------------------------------------------------------------------------------- | | [PY](/py/) | When you need the previous year instead of the previous week. | | [SHIFT](/shift/) | When you need a custom offset or want to shift along a specific time level. | | [WOW\_ABS](/wow-abs/) | When you need the absolute difference to the previous week, not just the shifted values. | --- # PY URL: https://docs.valsight.ai/py/ Description: Shifts the input node one year into the future while retaining all other dimensions. Use this when you need last year's values alongside current data for year-over-year comparisons. **Category:** [Compare periods](/compare-periods/) ## Overview The **PY** function **shifts the input node one year into the future** while retaining all other dimensions. Use this function when you need last year's values alongside current data for year-over-year comparisons. ## Syntax `PY('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | -------------------------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node that is shifted, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | ## Examples ### Shifting values by one year Each value appears one year later in the result. **Input node:** `'Profit'` | Year | Value | | ---- | ----- | | 2025 | 35 | | 2026 | 42 | | 2027 | 47 | **Formula:** `PY('Profit')` | Year | PY Result | | ---- | --------- | | 2026 | 35 | | 2027 | 42 | | 2028 | 47 | ### Shifting values by two years (nested PY) Nesting PY calls shifts values further into the future. Here, each value moves two years forward. Try [SHIFT](/shift/) as an alternative with a custom offset. **Input node:** `'Profit'` | Year | Value | | ---- | ----- | | 2025 | 38 | | 2026 | 45 | | 2027 | 52 | **Formula:** `PY(PY('Profit'))` | Year | PY Result | | ---- | --------- | | 2027 | 38 | | 2028 | 45 | | 2029 | 52 | ## Related | Function | When to use instead | | --------------------- | ---------------------------------------------------------------------------------------- | | [PQ](/pq/) | When you need the previous quarter instead of the previous year. | | [SHIFT](/shift/) | When you need a custom offset or want to shift along a specific time level. | | [YOY\_ABS](/yoy-abs/) | When you need the absolute difference to the previous year, not just the shifted values. | --- # Python Example URL: https://docs.valsight.ai/python-example/ Description: The following script connects to the api key endpoint, stores the cookie in the sessions and prints out all projects found in the instance. The following script connects to the api key endpoint, stores the cookie in the sessions and prints out all projects found in the instance. ``` import requests, os,sys, json baseurl = "https://instancename.valsight.eu/v1/" username = 'username-as-shown-on-userpage' api_key = '5bc333fe-xxxx-xxxx-xxxx-c04513aa2a0f' session = requests.Session() response = session.post( baseurl+ "apiKey", data={'username': username,'api_key': api_key}) r = session.get(baseurl+"projectSpaces/") for p in json.loads(r.text): print("ID: %i \tBusiness Key: %s \tName: %s" %(p["id"], p['businessKey'], p['name'])) ``` --- # QOQ_ABS URL: https://docs.valsight.ai/qoq-abs/ Description: Returns the absolute quarter-over-quarter growth by calculating the difference between the current and previous quarter. Missing quarters can be skipped or treated as zero, depending on the selected behavior. **Category:** [Compare periods](/compare-periods/) ## Overview The **QOQ\_ABS** function **returns the absolute growth for each quarter compared to the previous quarter** (quarter-over-quarter). Use this function when you need the absolute difference between consecutive quarters. ## Syntax `QOQ_ABS('Node' [, "MissingValueBehaviour"])` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------------- | -------------------------------------------------------- | -------------- | -------- | ------------------ | | **Node** | Input node, specified in single quotes (e.g. `'Profit'`) | Node reference | Yes | -- | | **MissingValueBehaviour** | How missing values are treated. | Keyword | No | `"IGNORE_MISSING"` | **MissingValueBehaviour options:** * `"IGNORE_MISSING"`: Missing rows are skipped. This is the default. * `"MISSING_AS_ZERO"`: Missing rows are treated as 0. ## Examples ### Default: ignoring missing values This example shows QOQ\_ABS with the default behavior. The missing quarter 2026-Q1 is skipped and 2026-Q2 is not calculated. **Input node:** `'Profit'` | Quarter | Value | | ------- | ----- | | 2025-Q1 | 200 | | 2025-Q2 | 300 | | 2025-Q3 | 450 | | 2025-Q4 | 500 | | 2026-Q2 | 100 | **Formula:** `QOQ_ABS('Profit')` **Equivalent to:** `QOQ_ABS('Profit', "IGNORE_MISSING")` | Quarter | QOQ\_ABS Result | | ------- | --------------- | | 2025-Q2 | 100 | | 2025-Q3 | 150 | | 2025-Q4 | 50 | ### Treating missing values as zero With MISSING\_AS\_ZERO, gaps are filled with 0, producing results for every quarter including those without input data. **Formula:** `QOQ_ABS('Profit', "MISSING_AS_ZERO")` | Quarter | QOQ\_ABS Result | | ------- | --------------- | | 2025-Q1 | 200 | | 2025-Q2 | 100 | | 2025-Q3 | 150 | | 2025-Q4 | 50 | | 2026-Q1 | -500 | | 2026-Q2 | 100 | | 2026-Q3 | -100 | ## Related | Function | When to use instead | | ------------------------- | -------------------------------------------------------------------------------------------- | | [QOQ\_REL](/qoq-rel/) | When you need the percentage change quarter-over-quarter instead of the absolute difference. | | [YOY\_ABS](/yoy-abs/) | When you need the absolute difference on a yearly basis instead of quarterly. | | [DELTA\_ABS](/delta-abs/) | When you need the absolute change along any dimension, not just time. | --- # QOQ_REL URL: https://docs.valsight.ai/qoq-rel/ Description: Returns the relative quarter-over-quarter growth (percentage change) between the current and previous quarter. Missing quarters can be skipped or treated as zero, depending on the selected behavior. **Category:** [Compare periods](/compare-periods/) ## Overview The **QOQ\_REL** function **returns the relative growth for each quarter compared to the previous quarter** (quarter-over-quarter). Use this function when you need the percentage change between consecutive quarters. ## Syntax `QOQ_REL('Node' [, "MissingValueBehaviour"])` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ------------------ | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | -- | | **MissingValueBehaviour** | How missing values are treated. | Keyword | No | `"IGNORE_MISSING"` | **MissingValueBehaviour options:** * `"IGNORE_MISSING"`: Missing rows are skipped. This is the default. * `"MISSING_AS_ZERO"`: Missing rows are treated as 0. ## Examples ### Default: ignoring missing values This example shows QOQ\_REL with the default behavior. The missing quarter 2026-Q1 is skipped and 2026-Q2 is not calculated. **Input node:** `'Profit'` | Quarter | Value | | ------- | ----- | | 2025-Q1 | 200 | | 2025-Q2 | 300 | | 2025-Q3 | 450 | | 2025-Q4 | 500 | | 2026-Q2 | 100 | **Formula:** `QOQ_REL('Profit')` **Equivalent to:** `QOQ_REL('Profit', "IGNORE_MISSING")` | Quarter | Calculation | Result | | ------- | ----------------- | ------ | | 2025-Q2 | (300 - 200) / 200 | 0.5 | | 2025-Q3 | 150 / 300 | 0.5 | | 2025-Q4 | 50 / 450 | 0.11 | ### Treating missing values as zero With MISSING\_AS\_ZERO, gaps are filled with 0, producing results for every quarter including those without input data. **Formula:** `QOQ_REL('Profit', "MISSING_AS_ZERO")` | Quarter | Calculation | Result | | ------- | ----------------- | ------ | | 2025-Q2 | (300 - 200) / 200 | 0.5 | | 2025-Q3 | 150 / 300 | 0.5 | | 2025-Q4 | 50 / 450 | 0.11 | | 2026-Q1 | (0 - 500) / 500 | -1 | | 2026-Q3 | (0 - 100) / 100 | -1 | 2026-Q2 is not present in the result: even with MISSING\_AS\_ZERO, dividing by a zero previous value causes a division by zero, so the entry is dropped. ## Related | Function | When to use instead | | ------------------------- | ----------------------------------------------------------------------------------- | | [QOQ\_ABS](/qoq-abs/) | When you need the absolute difference quarter-over-quarter instead of a percentage. | | [YOY\_REL](/yoy-rel/) | When you need the percentage change on a yearly basis instead of quarterly. | | [DELTA\_REL](/delta-rel/) | When you need relative change along any dimension, not just time. | --- # Quickstart: 10 common functions URL: https://docs.valsight.ai/quickstart-10-common-functions/ Description: This page highlights the functions you’ll use most often when bringing in data, shaping dimensionality, filtering slices, and building time logic. This page highlights the functions you’ll use most often when **bringing in data, shaping dimensionality, filtering slices, and building time logic**. Use it as a shortcut to common formula patterns before moving to the full [Function catalog](/function-catalog/). ## Connect & adjust values | Name | What it does | Formula | | -------------------- | -------------------------------------------------------------------------------- | ------------------------------------ | | [DATA](/data/) | Bring uploaded or source data into a node. Returns the referenced table's shape. | `DATA("Source", "Table", "Measure")` | | [ADDEACH](/addeach/) | Adjust each value individually, no aggregation. Keeps the input shape. | `ADDEACH('Node', Amount)` | ## Time logic & forecasting | Name | What it does | Formula | | ----------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------ | | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) | Project values forward with forecasting options. Extends the time range. | `ROLLFORWARD_ADVANCED('Node', ['Drivers'], ...)` | | [RUNNINGSUM](/runningsum/) | Calculate cumulative totals over time. Keeps the input shape. | `RUNNINGSUM('Node')` | ## Filter & apply business rules | Name | What it does | Formula | | ------------------ | ---------------------------------------------------------------------------- | ------------------------------------- | | [FILTER](/filter/) | Return a subset of a node, e.g. specific regions. Reduces to matching rows. | `FILTER('Node', "Level", Value)` | | [IF](/if/) | Apply thresholds, caps, floors, or branching. Follows the condition's shape. | `IF(Condition, ThenValue, ElseValue)` | ## Shape dimensionality | Name | What it does | Formula | | ------------------------------ | ------------------------------------------------------------------------- | ------------------------------------------- | | [EXPAND](/expand/) | Add dimensional detail. Expands to the cross product of the levels. | `EXPAND('Node', "Level", ...)` | | [EXPANDSINGLE](/expandsingle/) | Expand to specific level values only. Expands only to those values. | `EXPANDSINGLE('Node', "Level", Value, ...)` | | [DROPLEVEL](/droplevel/) | Remove dimensional detail. Drops a level and its finer levels. | `DROPLEVEL('Node', "Level", ...)` | | [ROLLUP](/rollup/) | Aggregate to a higher level, e.g. Month to Year. Reduces to those levels. | `ROLLUP('Node', "Level", ...)` | ## Related * [Formula basics](/formula-basics/): syntax, notation, and evaluation fundamentals * [Operators](/operators/): arithmetic, comparisons, boolean logic used in formulas * [Function catalog](/function-catalog/): all functions, from A to Z and by category --- # RATE URL: https://docs.valsight.ai/rate/ Description: Solves for the interest rate per period of an annuity, given the number of periods, the periodic payment, and the present value. **Category:** [Finance functions](/finance-functions/) ## Overview The **RATE** function **returns the interest rate per period of an annuity** based on a number of periods, the amount of payments per period, a present value, a future value, a value indicating whether payments are due at the beginning or the end of the period (type) and a guess. Use this function when the number of periods and payments are known and you want to solve for the implied interest rate. ## Syntax `RATE('Nper', 'Pmt', 'Pv' [, 'Fv' [, Type [, Guess]]])` ## Parameters | Parameter | Description | Type | Required | Default | | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | ------- | | **Nper** | Number of periods: the number of payments to be made. | Node reference | Yes | -- | | **Pmt** | Payment per period: the amount of each payment made. Payments/costs should ideally be entered as a negative number, for example `-500`, but this is not required. | Node reference | Yes | -- | | **Pv** | Present value: the current value of the annuity. | Node reference | Yes | -- | | **Fv** | Future value remaining after the final payment has been made. | Node reference | No | `0` | | **Type** | Indicates when payments are due (`1` = payment at beginning of period / annuity due, `0` = payment at end of period / ordinary annuity). Must be written as a plain number, not in quotes and not as a node reference. | Number | No | `0` | | **Guess** | A first guess for what the rate will be, as a decimal. Must be written as a plain number, not as a node reference. | Number | No | `0.1` | ## Watch out * `'Pv'` is the leading input node: its levels define the result's shape, and every other input is aligned to it. * Every other input may use only levels that also exist on `'Pv'`. It may use fewer levels, but not a level that `'Pv'` does not have. * On the levels it shares with `'Pv'`, each input must cover the same level values, otherwise the rows do not line up and the function returns an error. * Each input can also be a single number. * Giving every input the same levels as `'Pv'` skips an internal alignment step and improves performance. * `Guess` and the result are entered and returned as decimals, for example `10% = 0.1`. * The rate is solved iteratively (up to 150 iterations). If it cannot converge, the function returns an error; a `Guess` closer to the expected rate helps it converge. ## Examples ### Solve for the implied interest rate This example shows a standard annuity setup with a fixed number of periods, a recurring payment, and a present value. It returns the implied interest rate per period for the setup. | Parameter | Value | | ------------------------------------------------------------------------------------------------------------- | ----- | | `Nper` (Number of Periods) | 60 | | `Pmt` (Payment per Period - Amount) | -100 | | `Pv` (Present Value) | 5000 | | `Fv` (Future Value) | 0 | | `Type`
Payment at Beginning of Period (Annuity Due) = 1
Payment at End of Period (Ordinary Annuity) = 0 | 0 | | `Guess` | 0.1 | **Formula:** `RATE('Nper', 'Pmt', 'Pv', 'Fv', 0, 0.1)` | RATE Result | | ----------- | | 0.0062 | ## Related | Function | When to use instead | | -------------- | ------------------------------------------------------------------------------------------------------------------------ | | [NPER](/nper/) | When the rate is known and you want to calculate how many periods are needed instead. | | [IRR](/irr/) | When you need the break-even discount rate for a cash flow series instead of the implied rate of an annuity-style setup. | --- # RATIO URL: https://docs.valsight.ai/ratio/ Description: Divides one node by another while retaining only their shared dimensions, recalculating the ratio dynamically at each aggregation level. Intended for display-only ratios in dashboards and reports. **Category:** [Math & numeric](/math-numeric/) > **End-Node Restriction.** > The **RATIO** function should be an end node. It **should not be referenced by other nodes** or used in further calculations. Doing so will cause the dynamic recalculation behavior to be lost, producing potentially incorrect results. > > RATIO is designed for visualization and reporting purposes only. If you need a calculable ratio, see "Alternative: Division with Weighted-Average Aggregation" below. ## Overview The **RATIO** function **divides one node by another while retaining only the dimensions shared by both nodes.** Unlike a standard division (`'Node1' / 'Node2'`), RATIO dynamically recalculates the ratio at every aggregation level displayed in the workspace. For example, when switching from a monthly to a quarterly view, the ratio is recomputed from the quarterly totals rather than averaging the monthly ratios. Use this function when you need a ratio that stays correct across different aggregation levels in dashboards and reports. ## Syntax `RATIO('Node1', 'Node2')` **Example usage:** `RATIO('Revenue', 'Quantity')` ## Parameters | Parameter | Description | Type | Required | | --------- | ------------------------------------------- | -------------- | -------- | | **Node1** | Dividend. The node whose values are divided | Node reference | Yes | | **Node2** | Divisor. The node whose values divide Node1 | Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | -------------------------------------------------------------------------- | | Dimensionality | Only dimensions shared by both input nodes are kept | | Values | Values are recalculated dynamically per aggregation level in the workspace | | Row count | Depends on shared dimensional combinations | ## Watch out * RATIO is not a standard calculation node. * The function should not be referenced by other nodes. * The result is recomputed dynamically when the aggregation level changes. * Only shared dimensions between both nodes appear in the result. ## Examples ### Basic ratio **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 15 | | 2026 | 28 | | 2027 | 126 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 2 | | 2026 | 2 | | 2027 | 3 | **Formula:** `RATIO('A', 'B')` | Year | RATIO Result | | ---- | ------------ | | 2025 | 7.5 | | 2026 | 14 | | 2027 | 42 | At the individual year level, RATIO produces the same results as division. The difference appears when you aggregate: | Level | Plain division (incorrect) | RATIO (correct) | | ----- | ---------------------------------------------- | ------------------------------------------------------------------------- | | Total | Average of ratios: (7.5 + 14 + 42) / 3 = 21.2 | Recalculated from totals: (15 + 28 + 126) / (2 + 2 + 3) = 169 / 7 ≈ 24.1 | RATIO recomputes the division from the aggregated totals, giving the mathematically correct result. ### Inputs with different dimensions When Node1 and Node2 have different dimensions, only the shared dimensions appear in the result. **Input node:** `'Revenue'` | Year | Region | Value | | ---- | ------ | ----- | | 2025 | EMEA | 500 | | 2025 | APAC | 300 | | 2026 | EMEA | 600 | | 2026 | APAC | 400 | **Input node:** `'Headcount'` | Year | Value | | ---- | ----- | | 2025 | 50 | | 2026 | 55 | **Formula:** `RATIO('Revenue', 'Headcount')` | Year | Calculation | Result | | ---- | ---------------- | ------ | | 2025 | (500 + 300) / 50 | 16 | | 2026 | (600 + 400) / 55 | ≈ 18.2 | Region is not shared by both nodes, so it is not present in the output. Revenue is aggregated across regions before dividing by headcount. ## Alternative **Division with Weighted-Average Aggregation** If you need a ratio result that **can be used in further calculations**, do not use RATIO. **Instead**: 1. Create a regular division node: `'Node1' / 'Node2'` 2. Set the node's **aggregation type to "weighted average"** (with the divisor as the weight node). This produces a similar weighted ratio across aggregation levels, but the result is a standard node that can be referenced by other calculations. Note that the aggregation behavior may not be identical to RATIO in all cases. ## Related | Function | When to use instead | | -------------------------- | ----------------------------------------------------------------------------------- | | [DIVISION (/)](/division/) | When you want standard division that keeps the union of dimensions from both nodes. | | [DIVIDE](/divide/) | When you want division with validation for missing rows. | --- # REBOOK URL: https://docs.valsight.ai/rebook/ Description: The REBOOK function moves value measures from one level value to another within the same level, setting source values to zero and adding amounts to the target value. **Category:** [Dimensionality & hierarchies](/dimensionality-hierarchies/) ## Overview The **REBOOK** function **moves value measures from one level value to another within the same level**. The source values are set to zero and their amounts are added to the target value. An optional filter operation controls which level values are rebooked. Use this function when you need to reclassify values from one level value to another within the same level. ## Syntax `REBOOK('Node', "Level", "OldValue", "NewValue" [, "FilterOperation"])` **Example usage:** `REBOOK('Revenue', "Segment", "MINI", "LARGE")` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------- | ------------------------------------------------------------------------- | ------------------- | -------- | -------------- | | **Node** | Input node | Node reference | Yes | -- | | **Level** | The level in the input node whose values should be rebooked | Level name | Yes | -- | | **OldValue** | The source value(s) to rebook. Can be a single value or a list of values. | Level value or list | Yes | -- | | **NewValue** | The target value to rebook into. Must be a single value. | Level value | Yes | -- | | **FilterOperation** | Controls which level values match the OldValue for rebooking | Keyword | No | `"EQ"` (equal) | **FilterOperation options:** * `"EQ"`: Rebooks the measures of the level value(s) **equal** to OldValue. This is the **default**. * `"NEQ"`: Rebooks all measures of level values **not equal** to OldValue. * `"GT"`: Rebooks all measures of level values **greater than** OldValue (lexicographic order). * `"GTE"`: Rebooks all measures of level values **greater than or equal to** OldValue. * `"LT"`: Rebooks all measures of level values **less than** OldValue. * `"LTE"`: Rebooks all measures of level values **less than or equal to** OldValue. The comparison operators (GT, GTE, LT, LTE) use **lexicographic (alphabetical) order**. "Greater" means the level value starts with a letter that comes after the first letter of OldValue alphabetically. **See also:** [Comparisons & boolean operators](/comparisons-boolean-operators/) ## Output shape | Aspect | Behavior | | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as input. | | Level values | Same as input. Source values remain in the output with value **0**. Target value receives the rebooked amounts **added** to any existing value. | | Row count | Same as input. | ## Watch out * OldValue and NewValue must be **level values of the same level** specified in the formula. * REBOOK only works on the **lowest level** of a dimension. If you specify a higher level, the function fails. * If the node contains **linked levels**, you cannot rebook values of the linked-to dimension directly. Rebook via the initial dimension that the other dimension is linked to. REBOOK always keeps linked levels between dimensions. * **Do not use** this function if you want the node to have different linked levels than the initial dimension. ## Examples These examples show how values are moved from one segment to another within the same level, including list-based rebooking and filtered rebooking. **Input node:** `'Revenue'` | Year | Segment | Value | | ---- | ------- | ----- | | 2025 | MINI | 100 | | 2025 | COMPACT | 50 | | 2025 | LARGE | 10 | ### Rebook a single value This example moves the value of one segment into another existing segment. **Formula:** `REBOOK('Revenue', "Segment", "MINI", "LARGE")` | Year | Segment | Calculation | Result | | ---- | ------- | ----------- | ------ | | 2025 | MINI | 100 - 100 | 0 | | 2025 | COMPACT | N/A | 50 | | 2025 | LARGE | 10 + 100 | 110 | The value measure of MINI (100) is moved to LARGE. Since LARGE already had a value of 10, the rebooked amount is added (10 + 100 = 110). ### Rebook a list of values This example rebooks a list of source values into one target value. **Formula:** `REBOOK('Revenue', "Segment", ["MINI", "COMPACT"], "LARGE")` | Year | Segment | Calculation | Result | | ---- | ------- | ------------- | ------ | | 2025 | MINI | 100 - 100 | 0 | | 2025 | COMPACT | 50 - 50 | 0 | | 2025 | LARGE | 10 + 100 + 50 | 160 | Both MINI and COMPACT are rebooked to LARGE. Their combined value (150) is added to LARGE's existing value (10). ### Rebook with a filter operation This example uses the NEQ filter to rebook all values that do **not** match the source value. **Formula:** `REBOOK('Revenue', "Segment", "MINI", "LARGE", "NEQ")` | Year | Segment | Calculation | Result | | ---- | ------- | ----------- | ------ | | 2025 | MINI | N/A | 100 | | 2025 | COMPACT | 50 - 50 | 0 | | 2025 | LARGE | 10 + 50 | 60 | With NEQ, all segments **not equal** to MINI are rebooked to LARGE. So COMPACT's value (50) is moved to LARGE, while MINI is untouched. ## Related | Function | When to use instead | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | | [DISTRIBUTE](/distribute/) | When values should be split across multiple level values using weights instead of moved from one level value to another. | | [REDISTRIBUTE](/redistribute/) | When values should be redistributed within defined clusters rather than rebooked directly between level values. | --- # Recognized Column Names URL: https://docs.valsight.ai/recognized-column-names/ Description: The column headers a data source upload links to measures, time levels and the Sequence dimension automatically. ## Overview Valsight reads the header row of every uploaded sheet and tries to link each column to something in the project. The general rule is the one worth remembering: **a column whose header matches the name of a level in the project is linked to that level.** No configuration is needed, and this is what makes a well-named sheet load without any manual mapping. On top of that rule, Valsight recognizes the fixed header names listed below, which link to levels a project may not have named that way. Matching ignores case and surrounding spaces, so `Year`, `YEAR` and `year ` all behave identically. For guidance on naming your own columns and levels, see [Naming Guidelines](/naming-guidelines/). ## Columns that become measures A column with one of these headers is treated as a measure rather than a level: ``` AMOUNT, MEASURE, VALUE, MEASURE_DISTRIBUTION ``` This only applies while the column's type is still undetermined, so a column you have already mapped in the upload wizard is never overridden. ## Columns that link to the time dimension These headers link a column to a time level, provided the project has that level. The level value in the cells has to match the shape shown, otherwise the upload reports an invalid value. | Column header | Time level | Level value shape | Example | | ------------- | ---------- | ------------------------------------- | -------- | | YEAR | Year | four-digit year | 2025 | | QUARTER | Quarter | year, hyphen, `Q`, quarter number | 2025-Q4 | | MONTH | Month | year, hyphen, two-digit month | 2025-01 | | ISOMONTH | Month | year, hyphen, two-digit month | 2025-01 | | DATE | Day | eight digits, no separators | 20250101 | | SAPDATE | Day | eight digits, no separators | 20250101 | | BLDAT | Day | eight digits, no separators | 20250101 | | CALWEEK | Week | year, hyphen, `W`, two-digit ISO week | 2025-W04 | Which of these levels exist depends on the project. A week-based project has no Quarter and no Month level, and its top level holds the ISO week-based year, so a `YEAR` column links there instead. See [The time dimension](/time-dimension/) for both structures. ## Columns that link to the Sequence dimension The headers `SEQ` and `SEQUENCE` link a column to the Sequence level. Sequence level values are fixed-width and padded with leading spaces, and the padding depends on the configured maximum, so they need care in Excel. See [Configure the Sequence Dimension](/configure-the-sequence-dimension/). ## Related documentation * [The time dimension](/time-dimension/): how the time levels above come to exist * [Naming Guidelines](/naming-guidelines/): naming your own sheets, columns and levels * [Data Source Upload](/data-source-upload/): structuring the Excel file as a whole --- # REDISTRIBUTE URL: https://docs.valsight.ai/redistribute/ Description: Calculates a weighted redistribution of the RedistributionValue following the specified DistributionWeight, staying within the boundaries of clusters specified by the ClusterLevels. **Category:** [Dimensionality & hierarchies](/dimensionality-hierarchies/) ## Overview The **REDISTRIBUTE** function **calculates a weighted redistribution of the RedistributionValue following the specified DistributionWeight**. The redistribution stays within the boundaries of clusters, which can be specified by the provided `ClusterLevels`. Each value is redistributed exclusively on the elements within the same cluster, though not including the distributed element itself. For example, assume you have a dimension with the levels `"Product Category"` and `"Product"`. The function allows you to distribute a value for a single product across all other products within the same `"Product Category"`. The value will not be distributed onto any product in a different `"Product Category"`, and it will not be distributed on the product itself. Use this function when you want to redistribute values only within defined clusters instead of across the full available detail. ## Syntax `REDISTRIBUTE('RedistributionValue', 'DistributionWeight' [, "ClusterLevels"])` ## Parameters | Parameter | Description | Type | Required | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | -------- | | **RedistributionValue** | Input node with values that need to be redistributed, for example `'RedistributionValue'`. | Node reference | Yes | | **DistributionWeight** | Input node whose value distribution is used to calculate the redistribution, for example `'DistributionWeight'`. | Node reference | Yes | | **ClusterLevels** | Array of levels used to cluster the redistribution, for example `"Category"`. If no cluster levels are inserted, all values in `'DistributionWeight'` will be treated as belonging to a single cluster. | List of level names | No | ## Watch out * An error will appear if `'RedistributionValue'` and `'DistributionWeight'` have different levels. * An error will appear if `"ClusterLevels"` contains levels that are not present in `'RedistributionValue'` and therefore in `'DistributionWeight'`. * An error will appear if `"ClusterLevels"` contains multiple levels from the same dimension. * The result unit will be the same as the `'RedistributionValue'` input. ## Examples ### Redistribute within a category cluster This example shows redistribution within the same `"Category"` cluster. Values are only spread to other rows inside that cluster and never to the source row itself. **Input node:** `'RedistributionValue'` | Category | Type | Value | | -------- | --------- | ----- | | Land | Car | - | | Land | Truck | 2 | | Land | Motorbike | - | | Sea | Boat | -5 | **Input node:** `'DistributionWeight'` | Category | Type | DistributionWeight | | -------- | --------- | ------------------ | | Land | Car | 10 | | Land | Truck | 20 | | Land | Motorbike | 30 | | Sea | Boat | 40 | **Formula:** `REDISTRIBUTE('RedistributionValue', 'DistributionWeight', "Category")` | Category | Type | **Distribution Weight** | Redistribute Truck | Redistribute Boat | REDISTRIBUTE Result | | -------- | --------- | ----------------------- | -------------------------- | ----------------- | ------------------- | | Land | Car | 10 | 2 × (10 / (10 + 30)) = 0.5 | - | 0.5 | | Land | Truck | 20 | - | - | - | | Land | Motorbike | 30 | 2 × (30 / (10 + 30)) = 1.5 | - | 1.5 | | Sea | Boat | 40 | - | - | - | Redistribution calculations only need to be performed for `Truck` and `Boat` because they are the only rows in `'RedistributionValue'` that have non-zero values. For the `Truck` redistribution, `Boat` is not included because it is within a different `"Category"` value. For the `Boat` redistribution, there are no calculations because it is the only row within its category cluster. Without clustering, the same input redistributes across all available rows instead of staying within category boundaries. **Formula:** `REDISTRIBUTE('RedistributionValue', 'DistributionWeight')` | Category | Type | **Distribution Weight** | Redistribute Truck | Redistribute Boat | Calculation | Result | | -------- | --------- | ----------------------- | -------------------------------- | ---------------------------------- | -------------- | ------ | | Land | Car | 10 | 2 × (10 / (10 + 30 + 40)) = 0.25 | -5 × (10 / (10 + 20 + 30)) = -0.83 | 0.25 + (-0.83) | -0.58 | | Land | Truck | 20 | - | -5 × (20 / (10 + 20 + 30)) = -1.67 | N/A | -1.67 | | Land | Motorbike | 30 | 2 × (30 / (10 + 30 + 40)) = 0.75 | -5 × (30 / (10 + 20 + 30)) = -2.5 | 0.75 + (-2.5) | -1.75 | | Sea | Boat | 40 | 2 × (40 / (10 + 30 + 40)) = 1 | - | N/A | 1 | **Note:** Cases where there are multiple values for a single line, for example `Car`, can occur when clustering is in use and there are multiple changes to rows within the same cluster. ### Redistribute with additional non-cluster levels This example adds a `"Colour"` level that is not part of the clustering level. The influence of that extra level is removed automatically when building the weight distribution used for the redistribution. **Input node:** `'RedistributionValue'` | Category | Type | Colour | Value | | -------- | --------- | ------ | ----- | | Land | Car | White | - | | Land | Car | Black | - | | Land | Truck | White | 2 | | Land | Truck | Black | 3 | | Land | Motorbike | Black | - | | Land | Motorbike | White | - | | Sea | Boat | White | -5 | **Input node:** `'DistributionWeight'` | Category | Type | Colour | DistributionWeight | | -------- | --------- | ------ | ------------------ | | Land | Car | White | 10 | | Land | Car | Black | 10 | | Land | Truck | White | 10 | | Land | Truck | Black | 20 | | Land | Motorbike | Black | 10 | | Land | Motorbike | White | 5 | | Sea | Boat | White | 40 | **Formula:** `REDISTRIBUTE('RedistributionValue', 'DistributionWeight', "Category")` Before calculating the redistribution, the function removes the influence of `"Colour"` from the weighting node and builds the following internal distribution table automatically: | Category | Type | DistributionWeight | | -------- | --------- | ------------------ | | Land | Car | 20 | | Land | Truck | 30 | | Land | Motorbike | 15 | | Sea | Boat | 40 | The resulting redistributed values are then calculated as follows. | Category | Type | Colour | **Distribution Weight** | Redistribute Truck White | Redistribute Truck Black | Redistribute Boat White | REDISTRIBUTE Result | | -------- | --------- | ------ | ----------------------- | --------------------------- | --------------------------- | ----------------------- | ------------------- | | Land | Car | White | 10 | 2 × (20 / (20 + 15)) = 1.14 | - | - | 1.14 | | Land | Car | Black | 10 | - | 3 × (20 / (20 + 15)) = 1.71 | - | 1.71 | | Land | Truck | White | 10 | - | - | - | - | | Land | Truck | Black | 20 | - | - | - | - | | Land | Motorbike | Black | 10 | - | 3 × (15 / (20 + 15)) = 1.29 | - | 1.29 | | Land | Motorbike | White | 5 | 2 × (15 / (20 + 15)) = 0.86 | - | - | 0.86 | | Sea | Boat | White | 40 | - | - | - | - | ## Related | Function | When to use instead | | -------------------------- | -------------------------------------------------------------------------------------------------------------- | | [DISTRIBUTE](/distribute/) | When values should be distributed across the full available detail instead of staying within defined clusters. | | [REBOOK](/rebook/) | When values should be moved from one level value to another instead of being redistributed using weights. | --- # Release History URL: https://docs.valsight.ai/release-history/ Description: Overview of all Valsight major versions with their current minor version, support status, release date, end of support, and the SHA1 checksum of each release package. ## Overview For an overview of the new features in each Valsight version, check its [release notes](/release-notes/). To find out which version you are running, either check the login screen or the bottom of each administration page. | Major Version | Current Minor Version | Support Status | Release Date (Major Version) | End of Support (LTS only) | | -------------- | --------------------- | --------------- | ---------------------------- | ------------------------- | | [7.3](/7-3-0/) | 7.3.1 | Supported (LTS) | 2026-09-09 | 2027-02-28 | | [7.2](/7-2-0/) | 7.2.4 | Please upgrade | 2026-07-03 | — | | [7.1](/7-1-0/) | 7.1.6 | Please upgrade | 2026-04-30 | — | | [7.0](/7-0-0/) | 7.0.15 | Please upgrade | 2026-02-10 | 2026-08-30 | > **Info:** The next LTS release is planned for January 2027. ## Verifying downloads SHA1 checksums of the current release packages, in `sha1sum` format: ``` 9e28d02fc093db604a6aef0676fc2ae9fca3e34a valsight-server-7.3.1.zip 6d67bd82f372b7694ecf486f974b426084a6c5f4 valsight-server-with-vpm-7.3.1.zip d35b0d1506f3eac3ac94e2eea032c71d5a44d418 valsight-server-7.2.4.zip 8cc0079eaacedcff7e39ae4ed62fa0ecb77cadb9 valsight-server-7.1.6.zip 56362ad65450c47556b50c7c0eef16cd31948ae6 valsight-server-7.0.15.zip f340685a00fc4474f29a9ba02744cb7fc8eb7ea8 valsight-server-with-vpm-7.0.15.zip ``` To verify a download, save the checksums to a file named `SHA1SUMS` next to the downloaded package and check it (entries for packages you did not download are skipped): ``` sha1sum -c SHA1SUMS --ignore-missing ``` Or compute the hash and compare it manually: ``` sha1sum valsight-server-X.X.X.zip ``` On Windows, use PowerShell instead: ``` Get-FileHash -Algorithm SHA1 valsight-server-X.X.X.zip ``` All releases are additionally signed with a GPG key — see [Digitally Signed Releases](/digitally-signed-releases/) for how to verify the signature. --- # Release Notes URL: https://docs.valsight.ai/release-notes/ Description: Release Notes Release notes for each Valsight version, plus feature deprecations. --- # Resetting the Database CHANGELOGLOCK URL: https://docs.valsight.ai/resetting-the-database-changeloglock/ Description: If the Valsight Server process gets interrupted during a regular startup, the database may end up in a locked state. If the Valsight Server process gets interrupted during a regular startup, the database may end up in a locked state. To remove the lock, run the following query on the database. ```sql UPDATE DATABASECHANGELOGLOCK SET LOCKED=false, LOCKGRANTED=null, LOCKEDBY=null where ID=1; ``` --- # Responsive Chart Text Size URL: https://docs.valsight.ai/responsive-chart-text-sizes/ Description: Let chart, axis, table and KPI text scale with the size of the window, set per instance or per workspace. Responsive chart text sizing scales the text in your charts to the size of the window, so a sheet stays readable on a laptop and on a large display without being reformatted by hand. ## What it is When it is on, fixed breakpoints scale the text of: * chart labels and axis labels * chart titles and subtitles * table text * KPI tile fonts * text tile headings and body text * slider labels, assumption titles and before/after values | Window width | Font scaling | | ----------------------------- | -------------- | | **Small**, up to 999px | Compact text | | **Medium**, 1000px to 1800px | Standard text | | **Large**, 1801px to 3000px | Enlarged text | | **Extra large**, above 3000px | Maximized text | When it is off, charts keep their original font sizes and layout. ## When to use it * The same worksheet is opened on screens of very different sizes. * You present from a large display but build on a laptop. * Table text or KPI tiles are hard to read at some window sizes. ## Configuration It can be set at two levels, and the workspace setting wins. **Instance level**, an admin setting that becomes the default for all new workspaces: 1. Go to **Settings > Instance Settings**. 2. Find **Responsive Chart Text Size**. 3. Choose **On** or **Off**. This applies only to workspaces set to **Instance Default**, new ones included. A workspace that has never been set follows **Off** rather than the instance setting, so switching the instance setting on does not on its own change existing workspaces. **Off** is the instance default. **Workspace level**, which overrides the instance default: 1. Open the **Workspace Settings**. 2. Find **Responsive Chart Text Size**. 3. Choose **Instance Default** to inherit, **On** to force it on for this workspace, or **Off** to force it off. ![The Responsive Chart Text Size setting in the workspace settings](./images/5933072397.png) ## Good to know * **Existing workspaces are unaffected.** Turning the instance setting on changes new workspaces and those set to Instance Default, not workspaces that already carry an explicit On or Off. * **The breakpoints are fixed.** You choose whether text scales, not how much, and there are four steps rather than a smooth scale. * **It needs admin rights at instance level.** A user can only change their own workspace. ## Related * [Formatting Charts](/chart-configuration/): the other formatting options, including per data series styling. * [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/): set font color, style and orientation per data series. --- # Restructuring Data in Excel using Power Query URL: https://docs.valsight.ai/restructuring-data-in-excel-using-power-query/ Description: Learn to transform your Excel document to fit the guidelines for data used in Valsight with Power Query! Learn to transform your Excel document to fit the [guidelines for data used in Valsight](/data-upload-import-export-overview/) with Power Query! ## Overview Data sources uploaded to Valsight need to be correctly formatted as shown in the picture below. ![image-20230905-091921.png](./images/5220106253.png) If you have an Excel document that is not following those guidelines (e.g. the document in the picture below), there is an easy way of changing it into the correct format using Excel Power Query. ![PowerQuerySoldUnits.PNG](./images/5094216275.png) Create an empty Excel document and select 'Data' → 'Get Data' → 'From File' → 'Excel Worksheet'. Now select the file that contains the desired data. ![image-20220331-132131.png](./images/5094230824.png) Excel automatically imports the data. Now select 'Clean Data' to change the data structure in the Power Query-Editor. ![image-20220331-132205.png](./images/5094230832.png) ## Changing the data structure In this case, select 'Use First Row As Headers' to properly title the columns. In general, use the suitable tool for your need offered by the Power Query-Editor (e.g. "Remove Rows/Columns", "Split Column", …) to transform your table. ![image-20220331-132248.png](./images/5094215789.png) The next step is to select all the columns containing data. In this case this means selecting the columns '2017', '2018', '2019' and '2020'. Afterward, click 'Transform' → 'Unpivot Columns'. ![image-20220331-132309.png](./images/5094215767.png) Now the only thing left to do is rename the columns by double clicking on their title and to 'close & load'. ![image-20220331-132334.png](./images/5094215503.png) Congratulations, you have successfully restructured your data. The resulting worksheet is now linked to the original document. ![image-20220331-132405.png](./images/5094230784.png) ## Import data via direct filepath Power Query offers the opportunity to connect the desired file path directly, to receive the matching data. The first task is to create a table with one column and one row. You have to name the column (e.g. "Product") and the table (e.g. "Table") to reference them later. Now you write down the file path, which leads to the desired, data, to the only cell. ![image-20220331-132509.png](./images/5094215728.png) Afterward, you open the Power Query-Editor containing the advanced Editor, as seen below. Select your table and go ‘Data' → 'From Table/Range' → 'Home' → 'Advanced Editor’. There you type down the following command. Be careful to reference your table and column name correctly, furthermore the sheet reference ({\[Item="Tabelle1",..) of the desired data. ``` let my_source= Excel.Workbook(File.Contents(Text.From(List.First(Table.Column(Excel.CurrentWorkbook(){[Name="Table"]}[Content], "Product")) )), null, true), Sheet1_Sheet = my_source{[Item="Tabelle1",Kind="Sheet"]}[Data] in Sheet1_Sheet ``` ![image-20220331-132542.png](./images/5094215754.png) If you referenced everything correctly, the preview of the data becomes visible. Just do "Close & Load" to finish the process. ![image-20220331-132607.png](./images/5094215485.png) It's done, you created a new sheet that contains the data. A change or expansion of the referenced data will be adapted automatically. ![image-20220331-132632.png](./images/5094230788.png) ### Mapping Let's continue with the given data table. To expand or substitute the given data you can use the "Join" Functions of Power Query. You can add the additional data in different ways, usually by copying/pasting or manually. ![image-20220331-132725.png](./images/5094215763.png) Afterward, you convert the data into a second table by selecting the desired data and selecting 'From Table/Range'. ![image-20220331-132749.png](./images/5094215750.png) Now you close it and import it as a connection only. ![image-20220331-132813.png](./images/5094215785.png)![image-20220331-132832.png](./images/5094230776.png) By selecting 'Data' → 'Get Data' → 'Combine Query' → 'Merge' you reach the Merge Window. ![image-20220331-132853.png](./images/5094215741.png) There you select for each field one of the given data tables and mark the matching columns. ![image-20220331-132915.png](./images/5094230836.png) You can process with the resulting Power Query depending on your needs. To remove the "Productname" information you only need to delete the column. For more options push the shown icon and choose the information you want to keep. ![image-20220331-132939.png](./images/5094230820.png) Now, select 'Close & Load' and your new data table is ready. ![image-20220331-132955.png](./images/5094230828.png) ## Transforming a date to a Valsight month ``` = Table.AddColumn(#"Geänderter Typ1", "TEst", each Text.Combine( { Number.ToText(Date.Year([Month])), "-", Number.ToText(Date.Month([Month]),"00") })) ``` --- # Reverse Proxy URL: https://docs.valsight.ai/reverse-proxy/ Description: To allow for the use of the application behind a reverse proxy the following headers must be sent in requests: Running Valsight behind a reverse proxy requires a specific set of HTTP headers. This page lists the mandatory ones, the ones that need care, and an nginx example. ## HTTP headers To allow for the use of the application behind a reverse proxy the following headers must be sent in requests:

Header Name

Description

  • Host

The name of the server the request was sent to

  • X-Real-IP

The IP of the client making requests to the application

  • X-Forwarded-For

A comma separated list of all clients previously passed through when making the request

  • X-Forwarded-Proto

The protocol that was used to connect to the proxy (HTTP or HTTPS)

  • X-Forwarded-Port

The access port used, e.g. 443 for HTTPS.

The following headers should either be *unset* by the reverse proxy to secure the app from unvalidated redirects and forwards or need to be *validated / handled* by different measurements, e.g. being overwritten by additional intermediate proxies.

Header Name

Description

  • Forwarded

Contains forwarding information

  • X-Forwarded-Host

The original host requested by the client in the Host HTTP request header as the ‘Host’ gets overridden by the reverse proxy

  • X-Forwarded-Server

The hostname of the proxy server

  • X-Forwarded-Ssl

Whether SSL was activated on the request

  • X-Forwarded-Prefix

Prefix for all forwards

This will have to be configured in the reverse proxy itself, no configuration in the application is required. An example of how this can be done in nginx is shown below: ``` location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-Port 443; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host "" proxy_set_header X-Forwarded-Server "" proxy_set_header X-Forwarded-Ssl "" proxy_set_header X-Forwarded-Prefix "" proxy_set_header Forwarded "" } ``` It is possible view the HTTP request headers that are being received by the application via the Administrator UI. To navigate to this page first click on “Debug Views”: ![4770b93b-b283-4e8c-964c-6d5b7195f0d2.png](./images/5564301360.png) Then on the provided list of functions select “Show request headers”: ![e353459a-0487-4632-aeb8-700169393ffb.png](./images/5564858377.png) The application will then show a list of the HTTP request headers and their values that were received by the application. ## Optional headers for feature gating Available since 7.2.5 and 7.3.0. One OpenID Connect setting can be told to apply to some clients only, by naming a request header the reverse proxy sets for the clients in question. Today that is the alternative login link, configured with `requiredHeader` — see [Listing the link for some clients only](/openid-connect/#listing-the-link-for-some-clients-only). You choose the header name; Valsight only checks whether the header is present and never interprets its value. If you use such a setting, the proxy has to set that header on **every** request rather than pass a client-supplied one through, so that a copy sent by the client is always overwritten. Valsight reads the configured header alone, with no fallback to `X-Forwarded-For` or `X-Real-IP`, since a client writes those freely. Nothing needs configuring here otherwise: with no such header in place, the gated setting falls back to applying to every client rather than to none. ## Server context path If the application is configured to use a context path in the URL, it is strongly advised that the reverse proxy is configured to forward requests using the same value. If this is not done then depending on the server configuration the application may not resolve correctly. For example if the application’s conf.yml is configured as follows: ``` server: servlet: contextPath: '/api' ``` Then the reverse proxy is configured to forward request to the application using the ‘/api’ path. For the above example the NGINX configuration needs to be adjusted as follows: ``` location /api { proxy_pass http://127.0.0.1:8080/api; proxy_set_header Host $host; proxy_set_header X-Forwarded-Port 443; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host "" proxy_set_header X-Forwarded-Server "" proxy_set_header X-Forwarded-Ssl "" proxy_set_header X-Forwarded-Prefix "" proxy_set_header Forwarded "" } ``` --- # ROLLFORWARD URL: https://docs.valsight.ai/rollforward/ Description: The ROLLFORWARD function rolls the values of the Original Node forward with the influence of optional driver nodes. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **ROLLFORWARD** function **rolls the values of the Original Node forward with the influence of optional driver nodes.** Use this function when you want to project a base series forward starting after the last available value with one or more driver nodes. > **Function alternative** > > The difference between this function and [ROLLFORWARD\_MUL](/rollforward-mul/) is how they treat multiple influence nodes. `ROLLFORWARD` **sums** the effects and then applies them to the original node. `ROLLFORWARD_MUL` **multiplies** the effects and then applies them to the original node. ## Syntax `ROLLFORWARD('OriginalNode' [, 'DriverNode', ...])` **Example usage:** `ROLLFORWARD('Revenue', 'Inflation')` ## Parameters | Parameter | Description | Type | Required | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | -------- | | **Original Node** | Input node whose values are rolled forward, specified in single quotes (e.g.`'Revenue'`) | Node reference | Yes | | **Driver Node** | One or more driver nodes that influence the rollforward, specified in single quotes (e.g.`'Inflation'`). Multiple drivers can be provided as additional arguments. | Node reference | No | ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as the Original Node | | Values | Original values are preserved for existing time periods. Future periods are projected from the last value, adjusted by cumulative driver effects (or flat if no drivers). | | Row count | Expands to every time period of the horizon after the last original value, whether or not a driver has data there | ## Watch out * All input nodes (original and drivers) must have a **time level**. * The driver's time level cannot be **coarser** than the original node's time level (e.g. yearly driver with monthly original data is not allowed). * If a driver node is **not a percent node**, it is automatically converted to relative **period-over-period** changes at its own time level before being applied. * Original data values are **preserved as-is**. The rollforward only applies to time periods after the last existing data point. * With **multiple drivers**, effects are **summed** per period, then applied. Use `ROLLFORWARD_MUL` if you need multiplicative combination instead. * Driver nodes are automatically **rolled up** to match the dimensionality of the Original Node if they have finer granularity. * If no driver nodes are specified, the **last value is projected forward** as a flat line (0% growth). ## Examples ### Rollforward with a percentage driver This example uses a percentage driver. Each future period applies the driver value to the latest rolled result. **Original node:** `'Revenue'` | Year | Value | | ---- | ----- | | 2025 | 95 | | 2026 | 100 | **Driver node:** `'Inflation'` | Year | Value in % | | ---- | ---------- | | 2026 | 0.02 | | 2027 | 0.1 | | 2028 | 0.2 | **Formula:** `ROLLFORWARD('Revenue', 'Inflation')` | Year | ROLLFORWARD Result | | ---- | ------------------ | | 2025 | 95 | | 2026 | 100 | | 2027 | 110 | | 2028 | 132 | ### Rollforward with an absolute driver If the driver node is not a percent node, ROLLFORWARD first converts it into a relative growth effect per period, and then compounds that growth onto the latest rolled value. **Original node:** `'Revenue'` | Year | Value | | ---- | ----- | | 2025 | 95 | | 2026 | 100 | **Driver node:** `'Market Size'` | Year | Value | | ---- | ----- | | 2026 | 10000 | | 2027 | 10100 | | 2028 | 10500 | **Formula:** `ROLLFORWARD('Revenue', 'Market Size')` | Year | Calculation | Result | | ---- | ----------------------------------- | ------ | | 2025 | N/A | 95 | | 2026 | N/A | 100 | | 2027 | 100 × (10100/10000) | 101 | | 2028 | 100 × (10100/10000) × (10500/10100) | 105 | Market Size is converted to relative changes first: 2027 grows by 10100/10000 - 1 = 1%, and 2028 by 10500/10100 - 1 = 3.96%. Each future period then multiplies the previous result by 1 plus that growth, so a driver ratio is always a factor and never an addend. ### Rollforward with multiple driver nodes With multiple drivers, ROLLFORWARD sums the individual effects per period before applying them to the latest rolled value. **Driver node:** `'Inflation'` | Year | Inflation | | ---- | --------- | | 2026 | 10% | | 2027 | 10% | | 2028 | 10% | **Driver node:** `'Growth'` | Year | Growth | | ---- | ------ | | 2026 | 20% | | 2027 | 20% | | 2028 | 20% | **Original node:** `'Revenue'` | Year | Revenue | | ---- | ------- | | 2026 | 1000 | **Formula:** `ROLLFORWARD('Revenue', 'Inflation', 'Growth')` | Year | Calculation | Result | | ---- | ---------------------------------- | ------ | | 2027 | 1000 + (1000 × 0.1) + (1000 × 0.2) | 1300 | | 2028 | 1300 + (1300 × 0.1) + (1300 × 0.2) | 1690 | ## Related | Function | When to use instead | | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) | When you need a more configurable rollforward setup with explicit control over timing, base behavior, or advanced driver handling beyond the standard `ROLLFORWARD` logic. | | [ROLLFORWARD\_MUL](/rollforward-mul/) | When multiple drivers should influence each other within the same period instead of being summed first. | | [PREVIOUS](/previous/) | When you need older loop-style logic with a defined base case instead of a direct rollforward from the latest available value. | --- # ROLLFORWARD_ADVANCED URL: https://docs.valsight.ai/rollforward-advanced/ Description: ROLLFORWARD_ADVANCED is an advanced projection function that rolls data forward in time using drivers and optional parameters like aging levels, window settings, and projection modes to forecast future values based on historical data. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **ROLLFORWARD\_ADVANCED** function **projects a node into the future using a list of provided drivers**, combining the functionality of [ROLLFORWARD](/rollforward/) and [ROLLFORWARD\_MUL](/rollforward-mul/) into one function with additional controls. Unlike ROLLFORWARD, which rolls the last available value of each level value forward regardless of time period, ROLLFORWARD\_ADVANCED looks at a specific time period and projects the data available there into the future. Use this function when you need more control over a projection than ROLLFORWARD offers, for example driver combination mode, window aggregation, or aging levels. ## Common patterns | Name | What it does | Formula | | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | | Project with seasonality | Size the window to a full season so each period repeats the earlier one. See the [seasonality example](#example-for-seasonality-over-the-time-level-quarters). | `ROLLFORWARD_ADVANCED('Node', [], "Quarter", "2027-Q1", "2028-Q4", 4)` | | Compounding / loop projection | Project each period from the previous one so drivers compound. See the [multiplicative mode example](#rollforward_advanced-with-mode-configured). | `ROLLFORWARD_ADVANCED('Node', ['Driver'], ..., "MULTIPLICATIVE")` | | Age a level while projecting | Increment an aging level, such as contract age, on every loop step. See the [aging example](#rollforward_advanced-with-aginglevels-configured). | `ROLLFORWARD_ADVANCED('Node', ['Driver'], ..., ["Contract Age"])` | ## Syntax * Most cases: `ROLLFORWARD_ADVANCED('input' [, ['drivers']])` * Full syntax: `ROLLFORWARD_ADVANCED('input'[, ['drivers'] [, "time" [, "start", "end" [, windowSize [, "windowFunction" [, "windowType" [, "mode" [, ["agingLevels"] [, agingOffset] [, "linkedLevelsAggregation"]]]]]]]]]])` **Example usage:** `ROLLFORWARD_ADVANCED('Sold Ice Cream', 'New Locations', 'Marketing Activities')` Every parameter after `input` is optional and positional. To set a later one without the earlier ones, use the [custom parameter order](#custom-parameter-order). ## Parameters ### input **Type:** Node reference · **Required:** Yes · **Default:** -- The input with values that are to be projected. ### drivers **Type:** List of node references · **Required:** No · **Default:** None (no drivers) A list of nodes that will be applied as drivers. Relative drivers are determined by using the percentage unit on the node. Multiple drivers can, but do not need to, be placed in square brackets (this is mandatory when using a custom parameter order, see below). Every absolute driver must have the same levels as `input`; every relative driver must have the same levels, or a subset of the levels, of those on `input`. ### time **Type:** Level name · **Required:** No · **Default:** Lowest available time level of `input` The level that is used to project the input. The function calculates the projected values in a loop over the `time` level, calculating each value based on the value of the previous loop. For some use cases, this level can also be a non-time-dimensional level. The level must be available on `input`; it is required if `input` has no time level; and it must be the most granular level from its dimension on `input`. ### start **Type:** Level value · **Required:** No · **Default:** The `time` level value from `input` incremented by one The level value from `time` that the projection will begin at. Any value in `input` that comes before the `start` level value is left unchanged. Must be a value from `time`, and must not come after `end` within the `time` value dimension (this includes taking into consideration a higher level in the dimension than the `time` value). Setting `start` and `end` to the same value is allowed and projects a single period. ### end **Type:** Level value · **Required:** No · **Default:** The end of the horizon if `time` is a time level, otherwise the last value of the dimension The default depends on the kind of level `time` points at. For a time level the projection stops at the end of the project horizon. For a non-time level, which this function also allows, there is no horizon to stop at, so leaving `end` out projects to the last value of that dimension. The level value from `time` that the projection will end at. Any value in `input` that comes after the `end` level value is left unchanged. Must be a value from `time`, and must not come before `start` within the `time` value dimension. It may be the same value as `start`. ### windowSize **Type:** Number · **Required:** No · **Default:** `1` The number of previous values used for the loop calculation. The calculation is an aggregation of all values in the window using the provided `windowFunction`. For example, a `windowSize` of 1 means the current value is calculated only using the last previous value, while a size of 3 uses the previous 3 values. A window value will not be calculated until it is full. Must be `1` or larger. ### windowFunction **Type:** Keyword · **Required:** No · **Default:** `"FIRST"` The aggregation function to apply to the values within the window to calculate a value for each `time` iteration. * `"FIRST"`: the first value in the window. This is the default. * `"LAST"`: the last value in the window. * `"AVG"`: the average of the values in the window. * `"SUM"`: the sum of all values in the window. * `"PROD"`: the product of all values in the window. ### windowType **Type:** Keyword · **Required:** No · **Default:** `"ROLLING"` Determines whether the values in the window to which drivers are applied are updated while looping. * `"FIXED"`: the projection is always based on the initially defined window while looping. * `"ROLLING"`: while looping, the window that the projection is based on moves with the projection. This is the default. ### mode **Type:** Keyword · **Required:** No · **Default:** `"ADDITIVE"` Determines how `drivers` are applied. * `"ADDITIVE"`: each driver is applied additively in the provided order, with no cross effects between them. This is the default. * `"MULTIPLICATIVE"`: drivers are applied in the provided order one after another. Every driver is applied on the base including all previous drivers, so it can trigger cross effects between drivers. ### agingLevels **Type:** List of level names · **Required:** No · **Default:** None (no aging levels) A list of levels from `input` that are incremented/shifted with every loop iteration along the `time` value. For example, this can be used to increment a contract age every year when iterating over the years as the `time` value. Multiple levels can, but do not need to, be placed in square brackets (this is mandatory when using a custom parameter order, see below). Each `agingLevel` must be on `input`; must be the most granular level from its dimension on `input`; and cannot be from the same dimension as `time` or another `agingLevel`. This function always makes the links between the `input` and `agingLevel` dimensions match the dimension management. Do not use it if you want the node to have different level links than the dimensions. ### agingOffset **Type:** Number · **Required:** No · **Default:** `-1` The offset by which every `agingLevel` is incremented/shifted with every loop iteration. Follows the same format as the [SHIFT](/shift/) function, where `-1` increments the `agingLevel` by one value. Must be `-1` or less. ### linkedLevelsAggregation **Type:** Keyword · **Required:** No · **Default:** `"LAST"` Defines which values to select in cases where levels and linked-to-levels are not mapped to each other as specified in the dimension management ("ambiguous mapping"). Only applied if the incorrect links relate to a level within the same dimension as `time` or an `agingLevel`. The available [aggregation types](/aggregation-settings/) apply. ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Dimensionality | Same as `input`. When `agingLevels` are used, their links to other dimensions are set to match dimension management. | | Values | Values before `start` are left unchanged. From `start` to `end`, each period on the `time` level is projected from the window of prior values, with `drivers` applied according to `mode`. | | Row count | Extended to cover the projection range on the `time` level. | ## Watch out * `input` must have a time level, unless you pass an explicit `time` level to project over. * `time` must be the most granular level of its dimension on `input`. * Absolute drivers must have the same levels as `input`; relative drivers must have the same levels or a subset. * `start` must come before `end` on the `time` dimension; values outside that range are left unchanged. * Each `agingLevel` must be the most granular level of its dimension on `input`, and cannot share a dimension with `time` or another `agingLevel`. * `windowSize` must be `1` or larger, and a window is not calculated until it is full. ## Custom parameter order Instead of following the standard order, you can pass parameters by name. This lets you set any parameter without naming the ones before it. You can also mix the two, with positional parameters first, then named ones. ### How to use it * Name each parameter before its value, e.g. `ROLLFORWARD_ADVANCED(windowSize = 3, input = 'Revenue')`. * Use the names from the Parameters section above (case does not matter). * Do not quote the parameter name. Values keep their usual quoting: single quotes for nodes, double quotes for level names and values, no quotes for numbers. * Separate the name and value with `=`, optionally surrounded by spaces or line breaks. * A `drivers` or `agingLevels` list with more than one value must be in square brackets, so the parser knows where the list ends: `drivers = ['driver1', 'driver2']`. A single value needs no brackets: `drivers = 'driver1'`. ### Limitations * `input` is always required, regardless of order. * Once you name a parameter, every parameter after it must be named too. * Do not specify the same parameter twice. * If a parameter is given both positionally and by name, the named value wins. ### Example `ROLLFORWARD_ADVANCED('ExpandOneOnYearNode', mode = "MULTIPLICATIVE", windowFunction = "AVG", windowSize = 2)` Only `mode`, `windowFunction`, and `windowSize` are set here; every other parameter uses its default. ## Examples All examples use a time horizon of 2025 to 2031. ### ROLLFORWARD\_ADVANCED with no optional parameters **Input node:** `'Sold Ice Cream'` | Flavour | 2025 | 2026 | | ------- | ---- | ---- | | Lemon | 95 | 90 | | Cookies | | 100 | **Formula:** `ROLLFORWARD_ADVANCED('Sold Ice Cream')` | Flavour | 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | | ------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | | Lemon | 95 | 90 | 90 | 90 | 90 | 90 | 90 | | Cookies | | 100 | 100 | 100 | 100 | 100 | 100 | ### ROLLFORWARD\_ADVANCED with an absolute driver **Absolute driver:** `'New Locations'` | Flavour | 2027 | 2030 | 2031 | | ------- | ---- | ---- | ---- | | Lemon | 50 | | 100 | | Cookies | | 200 | | **Formula:** `ROLLFORWARD_ADVANCED('Sold Ice Cream', 'New Locations')` | Flavour | 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | | ------- | ---- | ---- | ------------- | ---- | ---- | --------------- | --------------- | | Lemon | 95 | 90 | 90 + 50 = 140 | 140 | 140 | 140 | 140 + 100 = 240 | | Cookies | | 100 | 100 | 100 | 100 | 100 + 200 = 300 | 300 | ### ROLLFORWARD\_ADVANCED with a relative driver **Relative driver:** `'Marketing Activities'` (unit = `Percent`) | 2027 | 2030 | 2031 | | ---- | ---- | ---- | | 0.02 | 0.1 | 0.2 | **Formula:** `ROLLFORWARD_ADVANCED('Sold Ice Cream', 'Marketing Activities')` | Flavour | 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | | ------- | ---- | ---- | ------------------------ | ---- | ---- | ---------------------------- | -------------------------------- | | Lemon | 95 | 90 | 90 + (90 × 0.02) = 91.8 | 91.8 | 91.8 | 91.8 + (91.8 × 0.1) = 100.98 | 100.98 + (100.98 × 0.2) = 121.18 | | Cookies | | 100 | 100 + (100 × 0.02) = 102 | 102 | 102 | 102 + (102 × 0.1) = 112.2 | 112.2 + (112.2 × 0.2) = 134.64 | ### ROLLFORWARD\_ADVANCED with `start` and `end` configured All previous examples use the default `start` of 2027 as the input data ends in 2026, and `end` of 2031 as this is the end of the horizon. This example shows how the range can be changed. **Formula:** `ROLLFORWARD_ADVANCED('Sold Ice Cream', [], "Year", "2027", "2029")` | Flavour | 2025 | 2026 | 2027 | 2028 | 2029 | | ------- | ---- | ---- | ---- | ---- | ---- | | Lemon | 95 | 90 | 90 | 90 | 90 | | Cookies | | 100 | 100 | 100 | 100 | ### ROLLFORWARD\_ADVANCED with `windowSize` configured This example sets `windowSize` to 2 instead of the default 1, so each value is calculated from the two previous values. This functionality can be used to project data while taking **seasonality** into account. **Formula:** `ROLLFORWARD_ADVANCED('Sold Ice Cream', [], "Year", "2027", "2031", 2)` | Flavour | 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | | ------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | | Lemon | 95 | 90 | 95 | 90 | 95 | 90 | 95 | | Cookies | | 100 | | 100 | | 100 | | #### Example for seasonality over the time level `Quarters` **Input node:** `'Sold Ice Cream in Quarters'` | Flavour | 2026-Q1 | 2026-Q2 | 2026-Q3 | 2026-Q4 | | ------- | ------- | ------- | ------- | ------- | | Lemon | 15 | 30 | 30 | 15 | | Cookies | 20 | 30 | 30 | 20 | **Formula:** `ROLLFORWARD_ADVANCED('Sold Ice Cream in Quarters', [], "Quarter", "2027-Q1", "2028-Q4", 4)` | Flavour | 2026-Q1 | 2026-Q2 | 2026-Q3 | 2026-Q4 | 2027-Q1 | 2027-Q2 | 2027-Q3 | 2027-Q4 | 2028-Q1 | 2028-Q2 | 2028-Q3 | 2028-Q4 | | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | | Lemon | 15 | 30 | 30 | 15 | 15 | 30 | 30 | 15 | 15 | 30 | 30 | 15 | | Cookies | 20 | 30 | 30 | 20 | 20 | 30 | 30 | 20 | 20 | 30 | 30 | 20 | ### ROLLFORWARD\_ADVANCED with `windowFunction` configured This example uses `windowFunction` `"SUM"` instead of the default `"FIRST"`, summing the values in the window instead of taking the first one. **Formula:** `ROLLFORWARD_ADVANCED('Sold Ice Cream', [], "Year", "2027", "2029", 2, "SUM")` | Flavour | 2025 | 2026 | 2027 | 2028 | 2029 | | ------- | ---- | ---- | ------------- | --------------- | --------------- | | Lemon | 95 | 90 | 95 + 90 = 185 | 90 + 185 = 275 | 185 + 275 = 460 | | Cookies | | 100 | 0 + 100 = 100 | 100 + 100 = 200 | 100 + 200 = 300 | The remaining parameters (`windowType`, `mode`, `agingLevels`, `agingOffset`, `linkedLevelsAggregation`) are omitted from this formula and use their default values. ### ROLLFORWARD\_ADVANCED with `windowType` configured This example uses `windowType` `"FIXED"` instead of the default `"ROLLING"`, so the projection stays based on the initially defined window instead of moving with it. **Absolute driver:** `'Additional Sales'` | Flavour | 2027 | 2028 | | ------- | ---- | ---- | | Lemon | 50 | 10 | | Cookies | | 200 | **Formula:** `ROLLFORWARD_ADVANCED('Sold Ice Cream', 'Additional Sales', "Year", "2027", "2029", 1, "FIRST", "FIXED")` | Flavour | 2025 | 2026 | 2027 | 2028 | 2029 | | ------- | ---- | ---- | ------------ | -------------- | ---- | | Lemon | 95 | 90 | 90 +50 = 140 | 90 +10 = 100 | 90 | | Cookies | | 100 | 100 | 100 +200 = 300 | 100 | The remaining parameters (`mode`, `agingLevels`, `agingOffset`, `linkedLevelsAggregation`) are omitted from this formula and use their default values. ### ROLLFORWARD\_ADVANCED with `mode` configured This example uses `mode` `"MULTIPLICATIVE"` instead of the default `"ADDITIVE"`, so each driver compounds on the base including all previous drivers. This functionality can be used to project data while taking **interest rates** into account. **Input node:** `'Account Balance (Base)'` | | 2025 | 2026 | | --------------- | ---- | ---- | | Account Balance | 95 | 90 | **Absolute driver:** `'Deposit'` | | 2027 | 2030 | 2031 | | -------- | ---- | ---- | ---- | | Deposits | 50 | | 100 | **Relative driver:** `'Additional Contributions'` (unit = `Percent`) | | 2027 | 2030 | 2031 | | ------------- | ---- | ---- | ---- | | Contributions | 0.02 | 0.1 | 0.2 | **Formula:** `ROLLFORWARD_ADVANCED('Account Balance (Base)', 'Deposit', 'Additional Contributions', "Year", "2027", "2031", 1, "FIRST", "ROLLING", "MULTIPLICATIVE")` | | 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | | --------------- | ---- | ---- | ------------------------------- | ----- | ----- | --------------------------------- | ---------------------------------- | | Account Balance | 95 | 90 | (90 + 50) × (1 + 0.02) = 142.8 | 142.8 | 142.8 | (142.8 + 0) × (1 + 0.1) = 157.08 | (157.08 + 100) × (1 + 0.2) = 308.5 | ### ROLLFORWARD\_ADVANCED with `agingLevels` configured This example adds an `agingLevels` configuration, incrementing Contract Age with every loop iteration instead of leaving it unchanged. This functionality can be used to project data while taking **contract aging** into account. **Input node:** `'Contracts'` | Contract Age | 2025 | 2026 | 2027 | | ------------ | ---- | ---- | ---- | | 1 | 95 | 90 | 70 | | 2 | | 100 | 90 | | 3 | | | 150 | **Absolute driver:** `'Additional Contracts'` | Contract Age | 2028 | 2029 | 2030 | 2031 | | ------------ | ---- | ---- | ---- | ---- | | 1 | 50 | | | | | 2 | | | 100 | | | 3 | | 600 | | 200 | **Relative driver:** `'Churn Rate'` | 2028 | 2030 | 2031 | | ----- | ---- | ---- | | -0.02 | -0.1 | -0.2 | **Formula:** `ROLLFORWARD_ADVANCED('Contracts', 'Additional Contracts', 'Churn Rate', "Year", "2028", "2031", 1, "FIRST", "ROLLING", "MULTIPLICATIVE", ["Contract Age"])` The square brackets are optional here, so this also works: **Equivalent to:** `ROLLFORWARD_ADVANCED('Contracts', 'Additional Contracts', 'Churn Rate', "Year", "2028", "2031", 1, "FIRST", "ROLLING", "MULTIPLICATIVE", "Contract Age")` | Contract Age | 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | | ------------ | ---- | ---- | ---- | -------------------------- | ------------------- | ------------------------- | -------------------------------- | | 1 | 95 | 90 | 70 | 50 × (1 + (-0.02)) = 49 | | | | | 2 | | 100 | 90 | 70 × (1 + (-0.02)) = 68.6 | 49 | 100 × (1 + (-0.1)) = 90 | | | 3 | | | 150 | 90 × (1 + (-0.02)) = 88.2 | 68.6 + 600 = 668.6 | 49 × (1 + (-0.1)) = 44.1 | (90 + 200) × (1 + (-0.2)) = 232 | ### ROLLFORWARD\_ADVANCED with `agingOffset` configured This example uses an `agingOffset` of -2 instead of the default -1, shifting `agingLevel` by two values per loop instead of one. **Input node:** `'Contracts'` | Contract Types | 2025 | 2026 | 2027 | | -------------- | ---- | ---- | ---- | | A | 95 | 90 | 70 | | B | | 100 | 90 | | C | | | 150 | **Absolute driver:** `'Additional Contracts'` | Contract Types | 2028 | 2029 | 2030 | 2031 | | -------------- | ---- | ---- | ---- | ---- | | A | 50 | | | | | B | | | 100 | | | C | | 600 | | 200 | **Relative driver:** `'Churn Rate'` | 2028 | 2030 | 2031 | | ----- | ---- | ---- | | -0.02 | -0.1 | -0.2 | **Formula:** `ROLLFORWARD_ADVANCED('Contracts', 'Additional Contracts', 'Churn Rate', "Year", "2028", "2031", 1, "FIRST", "ROLLING", "MULTIPLICATIVE", ["Contract Types"], -2)` | Contract Types | 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | | -------------- | ---- | ---- | ---- | ------------------------ | --------------- | ---------------------- | ----------------------- | | A | 95 | 90 | 70 | 50 × (1 + -0.02) = 49 | | | | | B | | 100 | 90 | | | 100 × (1 + -0.1) = 90 | | | C | | | 150 | 70 × (1 + -0.02) = 68.6 | 49 + 600 = 649 | | 200 × (1 + -0.2) = 160 | ### ROLLFORWARD\_ADVANCED with `linkedLevelsAggregation` configured Use this parameter when levels are mapped ambiguously. The example below shows what ambiguous mapping is and how the parameter resolves it. The initial link between levels in the dimension management might look like this: | Linked-from Level | Linked-to Level | | ------------------- | ----------------- | | Linked-from level 1 | Linked-to level 1 | | Linked-from level 2 | Linked-to level 2 | | Linked-from level 3 | Linked-to level 3 | In the unlikely case of ambiguous mapping, which could appear due to the effects of certain formula combinations, the data preview of a node might look like this: | Linked-to level | Linked-from level | 2031 | | ----------------- | ------------------- | ---- | | Linked-to level 1 | Linked-from level 1 | 1 | | Linked-to level 1 | Linked-from level 2 | 1 | | Linked-to level 1 | Linked-from level 3 | 1 | | Linked-to level 2 | Linked-from level 1 | 2 | | Linked-to level 2 | Linked-from level 2 | 2 | | Linked-to level 2 | Linked-from level 3 | 2 | | Linked-to level 3 | Linked-from level 1 | 3 | | Linked-to level 3 | Linked-from level 2 | 3 | | Linked-to level 3 | Linked-from level 3 | 3 | Due to an incorrect link between levels compared to the dimension management, this state is called "ambiguous mapping". Different `linkedLevelsAggregation` settings let you choose which values are used. The default `"LAST"` produces: | Linked-to Level | Linked-from Level | 2031 | | ----------------- | ------------------- | ---- | | Linked-to level 1 | Linked-from level 1 | 3 | | Linked-to level 2 | Linked-from level 2 | 3 | | Linked-to level 3 | Linked-from level 3 | 3 | ## Related | Function | When to use instead | | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | [ROLLFORWARD](/rollforward/) | When you need a straightforward additive projection from the last available value, without window, timing, or aging controls. | | [ROLLFORWARD\_MUL](/rollforward-mul/) | When you need a straightforward multiplicative projection from the last available value, without the additional controls. | | [PREVIOUS](/previous/) | When you need previous-period loop logic with an explicit base case rather than a full driver-based projection. | --- # ROLLFORWARD_MUL URL: https://docs.valsight.ai/rollforward-mul/ Description: ROLLFORWARD_MUL rolls the values of the Original Node forward, optionally influenced by one or more driver nodes whose effects are compounded multiplicatively. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **ROLLFORWARD\_MUL** function **rolls the values of the Original Node forward, optionally influenced by one or more driver nodes whose effects are compounded multiplicatively.** Use this function when multiple driver effects should compound with each other before being applied to the base node. Without drivers, the last value is carried forward as a flat projection. > **Function alternative** > > The difference between this function and [ROLLFORWARD](/rollforward/) is how they treat multiple influence nodes. `ROLLFORWARD` **sums** the effects and then applies them to the original node. `ROLLFORWARD_MUL` **multiplies** the effects and then applies them to the original node. ## Syntax `ROLLFORWARD_MUL('OriginalNode' [, 'DriverNode', ...])` **Example usage:** `ROLLFORWARD_MUL('Revenue', 'Price Change', 'Volume Change')` ## Parameters | Parameter | Description | Type | Required | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | | **Original Node** | Input node whose values are rolled forward, specified in single quotes (e.g.`'Revenue'`) | Node reference | Yes | | **Driver Node** | One or more driver nodes that influence the rollforward, specified in single quotes (e.g.`'Price Change'`). Multiple drivers can be provided as additional arguments. | Node reference | No | ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Dimensionality | Same as the Original Node | | Values | Original values are preserved for existing time periods. Future periods are projected from the last value, adjusted by cumulative compounded driver effects (or flat if no drivers). | | Row count | Expands to every time period of the horizon after the last original value, whether or not a driver has data there | ## Watch out * All input nodes (original and drivers) must have a **time level**. * The driver's time level cannot be **coarser** than the original node's time level (e.g. yearly driver with monthly original data is not allowed). * If a driver node is **not a percent node**, it is automatically converted to relative **period-over-period** changes at its own time level before being applied. * Original data values are **preserved as-is**. The rollforward only applies to time periods after the last existing data point. * With **multiple drivers**, effects are **multiplied** per period (compounded), not summed. Use `ROLLFORWARD` if you need additive combination instead. * Driver nodes are automatically **rolled up** to match the dimensionality of the Original Node if they have finer granularity. * Driver partitions that do not match the Original Node are **ignored**. For example, a driver value for country FR is ignored if the Original Node has no FR data. * If no driver nodes are specified, the **last value is projected forward** as a flat line (0% growth). ## Examples ### Compounding multiple drivers This example shows how a level-less percentage driver and a country-specific percentage driver are combined. The driver effects are multiplied first and then applied to the base value. **Original node:** `'Revenue'` | Year | Country | Value | | ---- | ------- | ----- | | 2025 | DE | 100 | | 2025 | US | 100 | **Driver node:** `'Price Change'` | Year | Value in % | | ---- | ---------- | | 2026 | 10% | **Driver node:** `'Volume Change'` | Year | Country | Value in % | | ---- | ------- | ---------- | | 2026 | DE | 10% | | 2026 | FR | 20% | **Formula:** `ROLLFORWARD_MUL('Revenue', 'Price Change', 'Volume Change')` | Year | Country | Calculation | Result | | ---- | ------- | ----------------------------- | ------ | | 2025 | DE | N/A | 100 | | 2025 | US | N/A | 100 | | 2026 | DE | 100 × ((0.1 + 1) × (0.1 + 1)) | 121 | | 2026 | US | 100 × (0.1 + 1) | 110 | Both countries receive a 10% growth from the level-less `Price Change` node. In addition, the DE row receives another 10% growth from `Volume Change`, compounding to 21% total. The FR row from `Volume Change` is ignored because FR is not present in the base node. US only receives the price change because no volume change is defined for US. ### Comparing SUM vs MUL with the same inputs This example highlights the difference between `ROLLFORWARD` (additive) and `ROLLFORWARD_MUL` (multiplicative). **Original node:** `'Revenue'` | Year | Revenue | | ---- | ------- | | 2026 | 1000 | **Driver node:** `'Inflation'` | Year | Value in % | | ---- | ---------- | | 2027 | 10% | **Driver node:** `'Growth'` | Year | Value in % | | ---- | ---------- | | 2027 | 20% | **Formula:** `ROLLFORWARD_MUL('Revenue', 'Inflation', 'Growth')` | Year | Calculation | Result | | ---- | ---------------------------- | ------ | | 2026 | N/A | 1000 | | 2027 | 1000 × (0.1 + 1) × (0.2 + 1) | 1320 | With `ROLLFORWARD` (additive), the same inputs would produce: 1000 + (1000 \* 0.1) + (1000 \* 0.2) = **1300**. The multiplicative version yields a higher result because the effects compound. ## Related | Function | When to use instead | | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) | When you need a more configurable rollforward setup with explicit control over timing, base behavior, or advanced driver handling beyond the standard `ROLLFORWARD` logic. | | [ROLLFORWARD](/rollforward/) | When you want to combine multiple driver effects additively before applying them to the base node instead of compounding them with each other. | --- # Rollforward & time series URL: https://docs.valsight.ai/rollforward-time-series/ Description: Use this category when you need time-based logic such as projections, running totals, moving windows, and timing effects. Use this category when you need **time-based logic** such as projections, running totals, moving windows, and timing effects. These functions operate along the time axis to help you forecast values into the future, build cumulative KPIs, smooth values over time, or model delayed impacts. ## Start here if you want to: * **Project values forward** using drivers * Use **cumulative KPIs** like `YTD` * Use **rolling windows** such as moving average or moving sum * Model **timing effects** such as delays or stretched profiles * Use a **previous-period** building block for loop logic ## Not here if you want to: * Use standard growth comparisons or deltas → see [Compare periods](/compare-periods/) * Reshape dimensionality → see [Dimensionality & hierarchies](/dimensionality-hierarchies/) ## Mental model * **Projection**: calculate future periods based on a base and driver logic * **Cumulative**: sum or multiply over time, either continuously or with periodic resets * **Rolling window**: aggregate across a sliding window of prior periods * **Timing effects**: shift or spread impacts across time * **Loop logic**: reference previous-period values with an explicit base case ## Common patterns | Name | What it does | Formula | | ---------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------- | | Project forward with drivers | Use when you want a flexible driver-based projection. | `ROLLFORWARD_ADVANCED('Base', 'Driver1', 'Driver2')` | | Build a running total | Use when you want cumulative values across the full time axis. | `RUNNINGSUM('Node')` | | Cumulative KPI with reset | Use when you want cumulative totals that reset within each year. | `YTD('Node')` | | Smooth values with a moving window | Use when you want a rolling average over prior periods. | `MOVINGAVG('Node', "TimeLevel", WindowSize)` | | Model delayed impact | Use when an effect should appear after a delay. | `TIMELAG('Node', 'TimeLagNode', "TimeLevel")` | | Loop logic with a base case | Use when you need loop-style logic with an explicit starting point. | `PREVIOUS('Node', "Level", 'BaseNode', "BaseValue")` | ## Functions in this category **Projection** | Function | Description | | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) | Projects a node into the future including the effects of defined driver nodes and optional parameters (e.g., seasonal/average projection, aging logic). | | [ROLLFORWARD](/rollforward/) | Projects a node into the future including the additive effects of defined driver nodes. | | [ROLLFORWARD\_MUL](/rollforward-mul/) | Projects a node into the future including the multiplicative effects of defined driver nodes. | **Cumulative and rolling calculations** | Function | Description | | ---------------------------- | -------------------------------------------------------------------------------------------------- | | [RUNNINGSUM](/runningsum/) | Calculates the cumulative sum along the time axis. | | [RUNNINGPROD](/runningprod/) | Calculates the cumulative product along the time axis. | | [MOVINGAVG](/movingavg/) | Returns the moving average of the current value and preceding values, as defined by a time window. | | [MOVINGSUM](/movingsum/) | Returns the moving sum of the current value and preceding values, as defined by a time window. | | **MTD** (see [YTD](/ytd/)) | Returns month-to-date values as a running sum per month over the lowest time level. | | **QTD** (see [YTD](/ytd/)) | Returns quarter-to-date values as a running sum per quarter over the lowest time level. | | [YTD](/ytd/) | Returns year-to-date values as a running sum per year over the lowest time level. | | **WTD** (see [YTD](/ytd/)) | Returns week-to-date values as a running sum per week over the lowest time level. | **Timing and loop logic** | Function | Description | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | [TIMELAG](/timelag/) | Applies time-lagged effects at a given time granularity to model delays or growth curves. | | [STRETCH\_CURVE](/stretch-curve/) | Stretches curves along the X-axis by a factor, starting at 0 by default or at an optional X position. | | [SCHEDULEPROJECTS](/scheduleprojects/) | Calculates a project KPI (e.g., revenue) over time given each project’s timing. | | [PREVIOUS](/previous/) | Returns the previous period’s value, except at a base period where it takes a specified base node value, enabling loop calculations. | **Statistical forecasting** | Function | Description | | ---------------- | --------------------------------------------------------------------------------- | | [ARIMA](/arima/) | Forecasts values using an autoregressive integrated moving average (ARIMA) model. | ## Choosing between similar functions **ROLLFORWARD\_ADVANCED vs ROLLFORWARD / ROLLFORWARD\_MUL** * Use `ROLLFORWARD_ADVANCED` when you need richer projection options and more control * Use `ROLLFORWARD` for additive drivers * Use `ROLLFORWARD_MUL` for multiplicative drivers **MTD/QTD/YTD/WTD vs RUNNINGSUM** * Use to-date functions for totals that reset within periods * Use `RUNNINGSUM` for a running total across the full time axis **MOVINGAVG/MOVINGSUM vs to-date functions** * Use moving functions for rolling windows * Use to-date functions for cumulative totals within the current period **PREVIOUS vs Compare periods shortcuts** * Use `PREVIOUS` when you need a base case and loop-style logic * Use `PM`/`PY`/`PQ`/`PW` for simple previous-period references **TIMELAG vs STRETCH\_CURVE** * Use `TIMELAG` for delayed effects * Use `STRETCH_CURVE` for stretching/compressing a profile ## Pitfalls & troubleshooting * **Future periods are missing in projections:** confirm the base series has values in the last actual period and drivers are defined for the projection range * **Projection results look wrong:** validate the base node and each driver node separately, then add drivers back one by one * **Cumulative totals are too large:** confirm whether you used `RUNNINGSUM` (no reset) versus `MTD/QTD/YTD/WTD` (resets) * **Moving windows look shifted:** verify the time level and window definition and confirm with spot checks in Data preview * **PREVIOUS behaves unexpectedly at the first period:** verify the base case and handle missing values explicitly if needed * **Timing effects feel wrong:** confirm the time granularity and whether you need a lag (`TIMELAG`) versus a profile stretch (`STRETCH_CURVE`) or project scheduling (`SCHEDULEPROJECTS`) ## Related * [Compare periods](/compare-periods/): standard growth comparisons and previous-period shortcuts * [Dimensionality & hierarchies](/dimensionality-hierarchies/): prepare output shape or create empty simulation space * [Troubleshooting guide](/troubleshooting-guide/): missing values and unexpected results * [Function catalog](/function-catalog/): full signatures, parameters, and examples --- # ROLLUP URL: https://docs.valsight.ai/rollup/ Description: The ROLLUP function aggregates values by reducing a node to only specified levels, removing all other levels and combining their values. **Category:** [Dimensionality & hierarchies](/dimensionality-hierarchies/) > **Syntax Change in Version 7.1:** This function no longer requires dimension names, only level names. Scroll to Version History for details. ## Overview The **ROLLUP** function **aggregates values by reducing a node to only the specified levels.** All other levels are removed and their values are aggregated. Use this function when you want to calculate totals or summaries across dimensions while keeping only the levels relevant for your analysis. ## Syntax `ROLLUP('Node', "Level1" [, "Level2", ...] [, "AggregationType"])` ## Parameters | Parameter | Description | Type | Required | Default | | ----------------------- | ----------------------------------------------------------------------------- | -------------- | -------- | ----------------------------------------------- | | **Node** | Input node, specified in single quotes (e.g. `'Sales'`) | Node reference | Yes | -- | | **Level1, Level2, ...** | Level names to keep in the output, specified in double quotes (e.g. `"Year"`) | Level name | No | -- | | **AggregationType** | Aggregation method for combining values | String | No | Node's own aggregation type (typically `"SUM"`) | **See also:** [Aggregation Settings](/aggregation-settings/) for all available aggregation methods ## Output shape | Aspect | Behavior | | ------------------- | ------------------------------------ | | Dimensionality | Reduces to only the specified levels | | Removed levels | All other levels are aggregated | | Row count | Reduced | | No levels specified | Returns a single number | ## Watch out * ROLLUP removes all levels that are not explicitly specified. * If no levels are provided, the result is a single aggregated value. * The specified levels must exist in the input node. * You can specify at most one level per dimension. * The specified level cannot be more granular than the levels present in the input node. ## Examples **Input node:** `'Sales'` Describes quantity of products sold across time and categories. | Product Group | Product | Year | Month | Value | | ------------- | --------- | ---- | ------- | ----- | | Cars | Model T | 2025 | 2025-01 | 11 | | Cars | Model T | 2025 | 2025-03 | 5 | | Motorcycles | V-Twin | 2026 | 2026-02 | 7 | | Motorcycles | 101 Scout | 2026 | 2026-01 | 19 | ### Rolling up to a single total Aggregates all values into one result. **Formula:** `ROLLUP('Sales')` | Calculation | Result | | --------------- | ------ | | 11 + 5 + 7 + 19 | 42 | ### Rolling up with average Uses AVG instead of the default SUM. **Formula:** `ROLLUP('Sales', "AVG")` | Calculation | Result | | --------------------- | ------ | | (11 + 5 + 7 + 19) / 4 | 10.5 | ### Rolling up to specific levels Keeps only `Year` and `Product Group`, aggregates everything else. **Formula:** `ROLLUP('Sales', "Year", "Product Group")` | Product Group | Year | Calculation | Result | | ------------- | ---- | ----------- | ------ | | Cars | 2025 | 11 + 5 | 16 | | Motorcycles | 2026 | 7 + 19 | 26 | ## Related | Function | When to use instead | | ------------------------- | ------------------------------------------------------------------- | | [ROLLUP\_TO](/rollup-to/) | When you want to match another node's dimensionality automatically. | | [DROPLEVEL](/droplevel/) | When you know which levels to remove rather than keep. | | [EXPAND](/expand/) | When you need to add levels instead of removing them. | ## Version history | Version | Change | | ------- | ------------------------------------------------------------------------------------------- | | 7.1 | Syntax simplified to level names only. Dimension names are no longer required or validated. | **Pre-7.1 Syntax (deprecated)** The previous syntax required dimension-level pairs: `ROLLUP('Node', "Dimension1", "Level1" [, "Dimension2", "Level2", …] [, "AggregationType"])` **Example (deprecated):** `ROLLUP('Sales', "Time", "Year", "Product", "Product Group")` **Migration:** Remove all dimension names, keep only level names: `ROLLUP('Sales', "Year", "Product Group")` --- # ROLLUP_TO URL: https://docs.valsight.ai/rollup-to/ Description: ROLLUP_TO automatically rolls up a node to match the dimensionality of another target node by removing extra levels and aggregating their values. **Category:** [Dimensionality & hierarchies](/dimensionality-hierarchies/) > **Syntax Change in Version 7.1:** The ROLLUP family no longer requires dimension names, only level names. Scroll to Version History for details. ## Overview The **ROLLUP\_TO** function **rolls up a node to match the level-dimensionality of another node**. All levels that exist in the first node but not in the second are removed, and their values are aggregated. Use this function when you want to automatically match one node's dimensionality to another without manually specifying which levels to keep. ## Syntax `ROLLUP_TO('Node1', 'Node2')` **Example usage:** `ROLLUP_TO('Profit', 'Budget')` ## Parameters | Parameter | Description | Type | Required | | --------- | ------------------------------------------------------------------------------------------------------------------ | -------------- | -------- | | **Node1** | The input node to be rolled up, specified in single quotes (e.g. `'Detail'`) | Node reference | Yes | | **Node2** | The target node whose level-dimensionality defines the output shape, specified in single quotes (e.g. `'Summary'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------ | | Dimensionality | Reduced to only the levels present in Node2 | | Values | Only the values of Node1 are used; Node2 only determines the shape | | Row count | Reduced. Values are aggregated across the removed levels | ## Watch out * Node2 cannot contain levels that are not in Node1. Every level in Node2 must also exist in Node1. * Node1 and Node2 cannot have the same set of levels. Node2 must have fewer levels than Node1, otherwise there is nothing to roll up. * The formula can feature only two inputs. * The values of Node2 are ignored. Only its dimensional structure matters. ## Examples **Input node:** `'Profit'` | Product Group | Product | Year | Month | Value | | ------------- | --------- | ---- | ------- | ----- | | Cars | Model T | 2025 | 2025-01 | 11 | | Cars | Model T | 2025 | 2025-03 | 5 | | Motorcycles | V-Twin | 2026 | 2026-02 | 7 | | Motorcycles | 101 Scout | 2026 | 2026-01 | 19 | **Target node:** `'Budget'` Budget data only has Product Group and Year. | Product Group | Year | Value | | ------------- | ---- | ----- | | Cars | 2025 | 50 | | Motorcycles | 2026 | 70 | ### Match dimensionality of a target node You want to compare actual quantities against budget, but the budget node only has Product Group and Year, no Product or Month detail. **Formula:** `ROLLUP_TO('Profit', 'Budget')` | Product Group | Year | Calculation | Result | | ------------- | ---- | ----------- | ------ | | Cars | 2025 | 11 + 5 | 16 | | Motorcycles | 2026 | 7 + 19 | 26 | Product and Month are removed because they don't exist in `Budget`. The values of `Budget` (50, 70) are not used, only its dimensional structure. ## Related | Function | When to use instead | | ------------------------ | --------------------------------------------------- | | [ROLLUP](/rollup/) | When you know exactly which levels to keep. | | [DROPLEVEL](/droplevel/) | When you know which levels to remove. | | [EXPAND](/expand/) | When you need to add levels instead of aggregating. | ## Version history | Version | Change | | ------- | -------------------------------------------------------------------------------------------------- | | 7.1 | Rollup syntax simplified to level names only. Dimension names are no longer required or validated. | **Pre-7.1 Syntax (deprecated)** The previous [ROLLUP](/rollup/) syntax required dimension-level pairs: `ROLLUP('Node', "Dimension1", "Level1" [, "Dimension2", "Level2", …] [, "AggregationType"])` **Example (deprecated):** `ROLLUP('Sales', "Time", "Year", "Product", "Product Group")` **Migration:** Remove all dimension names, keep only level names: `ROLLUP('Sales', "Year", "Product Group")` --- # ROUND URL: https://docs.valsight.ai/round/ Description: The ROUND function rounds each value of the input node to the specified number of decimal digits. The rounding behavior and precision can be controlled with optional parameters. **Category:** [Math & numeric](/math-numeric/) ## Overview The **ROUND** function **rounds each value of the input node to the specified number of decimal digits**. The rounding behavior and precision can be controlled with optional parameters. Use this function when you need stable rounding for reporting, presentation, or downstream calculation steps. ## Syntax `ROUND('Node' [, "RoundingMode" [, Scale]])` **Example usage:** `ROUND('Revenue', "HALF_UP", 2)` ## Parameters | Parameter | Description | Type | Required | Default | | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | -- | | **RoundingMode** | Specifies the rounding behavior. Case-insensitive. | Keyword | No | HALF\_UP | | **Scale** | Number of decimal digits to round to.`0` rounds to whole numbers, `2` rounds to two decimal places, `-2` rounds to whole hundreds. | Number | No | 0 | **Rounding modes:** * `"HALF_UP"`: Rounds towards the nearest neighbor. If equidistant (e.g. 2.5), rounds up. This is the default and the most common rounding mode. * `"HALF_DOWN"`: Rounds towards the nearest neighbor. If equidistant, rounds down. * `"HALF_EVEN"`: Rounds towards the nearest neighbor. If equidistant, rounds towards the even neighbor ("banker's rounding"). * `"UP"`: Rounds away from zero. Always increases the absolute value. * `"DOWN"`: Rounds towards zero. Always decreases the absolute value (truncation). * `"CEILING"`: Rounds towards positive infinity. Positive values round up, negative values round towards zero. * `"FLOOR"`: Rounds towards negative infinity. Positive values round down, negative values round away from zero. **See also:** [Java RoundingMode documentation](https://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html) ## Output shape | Aspect | Behavior | | -------------- | ---------------------------------------------------------------- | | Dimensionality | Same as input. | | Values | Each value is rounded according to the specified mode and scale. | | Row count | Same as input. | ## Watch out * **Scale requires RoundingMode.** You cannot specify a scale without also specifying a rounding mode. `ROUND('Node', 2)` is not valid. Use `ROUND('Node', "HALF_UP", 2)` instead. * **Negative scale** rounds to powers of 10: scale `-1` rounds to tens, `-2` to hundreds, `-3` to thousands. * Rounding is applied **element-wise** to each value independently. ## Examples ### Rounding with different modes and scales This example shows how ROUND behaves with the default mode, with explicit upward rounding, and with downward rounding to tens. The same decimal input is used for all three formulas. **Input node:** `'DecimalNode'` | Year | Revenue | | ---- | ------- | | 2025 | -24.50 | | 2026 | 95.99 | | 2027 | 100.0 | | 2028 | 133.33 | **Formula:** `ROUND('DecimalNode')` | Year | ROUND Result | | ---- | ------------ | | 2025 | -25 | | 2026 | 96 | | 2027 | 100 | | 2028 | 133 | Default: HALF\_UP with scale 0 (round to whole numbers). **Formula:** `ROUND('DecimalNode', "UP")` | Year | ROUND Result | | ---- | ------------ | | 2025 | -25 | | 2026 | 96 | | 2027 | 100 | | 2028 | 134 | UP rounds away from zero. 133.33 rounds up to 134. **Formula:** `ROUND('DecimalNode', "DOWN", -1)` | Year | ROUND Result | | ---- | ------------ | | 2025 | -20 | | 2026 | 90 | | 2027 | 100 | | 2028 | 130 | DOWN with scale -1 truncates towards zero and rounds to the nearest ten. ## Related | Function | When to use instead | | ------------ | -------------------------------------------------------------------------- | | [MAX](/max/) | When you need a simple cap or lower threshold instead of rounding a value. | | [MIN](/min/) | When you need a simple floor or upper threshold instead of rounding logic. | --- # Running Inside Docker URL: https://docs.valsight.ai/running-inside-docker/ Description: This article does not apply to Cloud installations. This article does not apply to Cloud installations. Valsight runs without problems in Docker containers. Contact our support if you need further assistance on the configuration of a container. --- # RUNNINGPROD URL: https://docs.valsight.ai/runningprod/ Description: RUNNINGPROD calculates the cumulative product of a node along the time axis, multiplying each value by all preceding values in the time series. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **RUNNINGPROD** function **calculates the cumulative product of a node along the time axis**. Each value is multiplied by all preceding values in the time series. Use this function when you need to accumulate multiplicative effects over time, such as chained growth factors. ## Syntax `RUNNINGPROD('Node')` **Example usage:** `RUNNINGPROD('GrowthFactor')` ## Parameters | Parameter | Description | Type | Required | | --------- | --------------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g.`'GrowthFactor'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as input. | | Values | Each value is the product of all values from the first time period up to and including the current one. | | Row count | Expands. Periods before the first value are dropped, then every period of the project horizon from the first value onwards gets a row. | ## Watch out * The input must have a **time level**. If the input has no time dimension, the function fails. * A **zero value** at any point makes all subsequent values zero, since every following product includes that zero. * A **missing period** after the first value is not a zero. It is skipped, which is the same as multiplying by 1, and the cumulative product is carried forward unchanged. * The accumulation starts from the **first time period** in the series. There is no window parameter. * The accumulation is computed **independently** for each combination of non-time dimensions. * The result runs to the **end of the project horizon**, not to the input's last period. Once the accumulation has started, gaps are filled and the running product is carried forward across every remaining period. ## Examples ### Cumulative product over time This example shows how RUNNINGPROD multiplies each value by all previous values along the time axis. **Input node:** `'GrowthFactor'` | Year | Value | | ---- | ----- | | 2025 | 1.1 | | 2026 | 1.2 | | 2027 | 1.2 | **Formula:** `RUNNINGPROD('GrowthFactor')` | Year | Calculation | Result | | ---- | --------------- | ------ | | 2025 | N/A | 1.1 | | 2026 | 1.1 × 1.2 | 1.32 | | 2027 | 1.1 × 1.2 × 1.2 | 1.584 | ### Compounding a base value with growth rates Multiplying a base value by the running product of (1 + growth rate). **Input node:** `'GrowthRate'` (as decimal, e.g. 0.05 = 5%) | Year | Value | | ---- | ----- | | 2025 | 0.05 | | 2026 | 0.10 | | 2027 | 0.03 | | 2028 | 0.00 | **Formula:** `RUNNINGPROD(ADDEACH('GrowthRate', 1))` | Year | Calculation | Result | | ---- | ------------------------- | ------- | | 2025 | N/A | 1.05 | | 2026 | 1.05 × 1.10 | 1.155 | | 2027 | 1.05 × 1.10 × 1.03 | 1.18965 | | 2028 | 1.05 × 1.10 × 1.03 × 1.00 | 1.18965 | Multiplying a base value (e.g. 1000) by this result gives the compounded projection: 1000 \* 1.18965 = 1189.65 in 2028. ## Related | Function | When to use instead | | -------------------------- | ------------------------------------------------------------------------------------------------------------ | | [RUNNINGSUM](/runningsum/) | When you need additive accumulation over time instead of a cumulative product. | | [FACT](/fact/) | When you need multiplication across discrete integer steps rather than a running product over a time series. | --- # RUNNINGSUM URL: https://docs.valsight.ai/runningsum/ Description: RUNNINGSUM calculates a cumulative total along the time axis, where each period's value equals the sum of all values from the first non-empty period up to and including the current period. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **RUNNINGSUM** function **calculates a cumulative total along the time axis**. Each period's value equals the sum of all values from the first non-empty period up to and including the current period. Use this function when you want to track how values accumulate over time or as a helper function. ## Syntax `RUNNINGSUM('Node')` **Example usage:** `RUNNINGSUM('Profit')` ## Parameters | Parameter | Description | Type | Required | | --------- | ---------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Preserves the input shape | | Row count | Expands. Periods before the first value are dropped, then every period of the project horizon from the first value onwards gets a row. | | Time range | Each period accumulates all preceding values | | Non-time behavior | Running sum is calculated independently for each combination | ## Watch out * RUNNINGSUM requires a time dimension in the input node. * The cumulative calculation follows the chronological order of the time hierarchy. * Each combination of non-time dimensions is accumulated independently. * Periods before the first non-empty value are omitted from the output. * The result runs to the **end of the project horizon**, not to the input's last period. Once the accumulation has started, gaps are filled and the running total is carried forward across every remaining period, so the output usually has more rows than the input. * Missing values after the first non-empty period are treated as zero. ## Examples ### Basic cumulative total **Input node:** `'Profit'` | Year | Value | | ---- | ----- | | 2025 | 10 | | 2026 | 20 | | 2027 | 15 | **Formula:** `RUNNINGSUM('Profit')` | Year | Calculation | Result | | ---- | ------------ | ------ | | 2025 | N/A | 10 | | 2026 | 10 + 20 | 30 | | 2027 | 10 + 20 + 15 | 45 | ### Multi-dimensional input When the node has additional dimensions (e.g. Region), the running sum is calculated independently for each dimensional combination. **Input node:** `'Revenue'` | Year | Region | Value | | ---- | ------ | ----- | | 2025 | EMEA | 50 | | 2026 | EMEA | 60 | | 2025 | APAC | 30 | | 2026 | APAC | 40 | **Formula:** `RUNNINGSUM('Revenue')` | Year | Region | Calculation | Result | | ---- | ------ | ----------- | ------ | | 2025 | EMEA | N/A | 50 | | 2026 | EMEA | 50 + 60 | 110 | | 2025 | APAC | N/A | 30 | | 2026 | APAC | 30 + 40 | 70 | Each region accumulates its values independently over time. ### Behavior with gaps in the data When the input has missing values for some time periods, RUNNINGSUM skips leading empty periods and treats later gaps as zero. **Input node:** `'Payments'` | Year | Value | | ---- | ----- | | 2024 | *N/A* | | 2025 | 100 | | 2026 | *N/A* | | 2027 | 50 | **Formula:** `RUNNINGSUM('Payments')` | Year | Calculation | Result | | ---- | ------------ | ------ | | 2025 | N/A | 100 | | 2026 | 100 + 0 | 100 | | 2027 | 100 + 0 + 50 | 150 | 2024 is omitted from the output because it is a leading empty period. 2026 has no value, so it is treated as zero, the running total carries forward unchanged. ## Related | Function | When to use instead | | ----------------------------------------------- | ----------------------------------------------------------------------------- | | [YTD](/ytd/) | When you need running totals that reset within each year. | | [RUNNINGPROD](/runningprod/) | When you need cumulative multiplication along the time axis. | | [MOVINGSUM](/movingsum/) | When you need a sum over a sliding window instead of from the start. | | [MOVINGAVG](/movingavg/) | When you need an average over a sliding window instead of a cumulative total. | | [ROLLFORWARD\_ADVANCED](/rollforward-advanced/) | When you want to project values forward in time. | --- # SAML URL: https://docs.valsight.ai/saml/ Description: To configure the Valsight application as a Service Provider (SP) in a SAML infrastructure, edit conf/config.yml and restart the server after making changes. To configure the Valsight application as a Service Provider (SP) in a SAML infrastructure, edit *conf/config.yml* and restart the server after making changes. To enable SAML login configure the following value: | Configuration Key (loginMethodConfigurations → saml →) | Description | Example Value | Default Value | | ------------------------------------------------------ | ------------------------------------------------- | ------------- | ------------- | | enabled | Whether SAML authentication should be used or not | true | false | Note: In order for SAML to be enabled, the same-site attribute for session cookie should be set to “none” with secure: true | Configuration Key (server → servlet → session → cookie → ) | Description | Example Value | Default Value | | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ------------- | | same-site | Restricts the usage of the cookie for the browser. The restriction is based on the originating event, which instructed the browser to send the cookie | none | strict | | secure | Ensures that the cookie is only sent over HTTPS connections. If same-site is set to none, secure **must** be set to true | false | true | To configure a SAML connection enter the following configuration keys: ``` spring: security: saml2: relyingparty: registration: SAML: ........ ``` Then configure the SAML connection values as follows: | Configuration key | Description | Example | Default | | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------- | | `entity-id` | The Identity Provider (IdP) entity ID. Must match your metadata XML entity. | `https://idp.example.com` | n/a | | `signing → credentials` | Location of the private key used to sign SAML authentication requests, and of the RelyingPartyX509Certificate shared with the identity provider. See [Credential locations](#credential-locations). | See [Credential locations](#credential-locations) | n/a | | `decryption → credentials` | Location of the private key used to decrypt the SAML authentication request, and of the RelyingPartyX509Certificate shared with the identity provider. See [Credential locations](#credential-locations). | See [Credential locations](#credential-locations) | n/a | | `assertingparty → metadata-uri` | URL to the Identity Provider (IdP) metadata. Takes a URL, a file path or a class path. See [Credential locations](#credential-locations) for how class paths resolve. | `http://idp.example.com/idp-metadata.xml` | n/a | | `valsightSamlProperties → name-id-format` | Removed in 6.1.0. See [Removed: name-id-format](#removed-name-id-format). | `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` | n/a | | `valsightSamlProperties → loginSuccessfulUrl` | The absolute URL, starting with `http` or `https`, of the application's main page. The user is redirected there after a successful login. Optional. | `https://valsight.example.com/` | n/a | | `valsightSamlProperties → userProfileMapping → username` | The SAML response attribute used to uniquely identify a user. Must always be present in the response, and unique per user. Optional. | `preferred_username` | The SAML user ID | | `valsightSamlProperties → userProfileMapping → email` | The SAML response attribute that contains the user's e-mail address. Optional. | `email` | n/a | | `valsightSamlProperties → userProfileMapping → fullName` | The SAML response attribute that contains the user's full name. Optional. | `name` | n/a | | `valsightSamlProperties → mandatoryAttributes` | Customizes which SAML response attributes must be present, and with which values. See [Mandatory attributes](#mandatory-attributes). Optional. | See [Mandatory attributes](#mandatory-attributes) | n/a | | `valsightSamlProperties → groupsAttribute` | The SAML response attribute holding the groups the user belongs to. See [Group synchronization](#group-synchronization). Optional. | `groupsInSAMLResponse` | n/a | | `valsightSamlProperties → signingAlgorithms → RSA` | Removed in 6.1.0. See [Removed: signingAlgorithms](#removed-signingalgorithms). | `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256` | `http://www.w3.org/2001/04/xmldsig-more#rsa-sha1` | ### Credential locations The signing and decryption credentials each take a `private-key-location` and a `certificate-location`. Both accept either a file path or a class path. When a class path is used, the root folder is the resources folder in the rest-service. | Key | File path | Class path | | ---------------------- | ----------------------------------- | ---------------------------------------- | | `private-key-location` | `file:./conf/saml/signing_key.key` | `classpath:credentials/signing_key.key` | | `certificate-location` | `file:./conf/saml/signing_cert.crt` | `classpath:credentials/signing_cert.crt` | Each of these can be a list of paired keys and certificates. The `-` character is required before every `private-key-location` value. ### Removed: name-id-format Removed in 6.1.0. The application now defaults to the format specified in the IdP's metadata. Before 6.1.0 this set the name ID format used when communicating with the IdP, and had to be one of `urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified`, `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`, `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent` or `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`. ### Mandatory attributes Every attribute configured here must be present in the provider's response and carry the specified value. Where an attribute has multiple values in the response — a list of the user's groups, for example — one of those values must match the configured value exactly. MIGRATETOKEN1ENDTOKEN These are both example attributes and values. Any attribute name and value can be used, provided they are included in the SAML token attributes. ### Group synchronization Setting `groupsAttribute` turns on group synchronization. If the attribute is absent or empty, groups must be managed inside the application instead. The value should be an attribute name of the SAML response (see the [OASIS SAML subject-id attribute specification](https://docs.oasis-open.org/security/saml-subject-id-attr/v1.0/cs01/saml-subject-id-attr-v1.0-cs01.html#_Toc536097223)) that contains the groups the IdP provides. Group matching then happens as follows: 1. Read the groups from the SAML response. 2. Create groups that are missing in the application. 3. Add the user to all groups from the response. 4. Remove the user from all groups not in the response. This functionality never automatically deletes groups in the application. ### Removed: signingAlgorithms Removed in 6.1.0. The application now defaults to `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`. Before 6.1.0 this chose the algorithm used to sign the XML requests the application creates. The possible values are listed in the [XML Signature Syntax and Processing specification](https://www.w3.org/TR/xmldsig-core1/#sec-SignatureAlg). The `RSA` key can be replaced with any of the listed signature methods, and `signingAlgorithms` accepts several signature method configurations at once. To get the application SAML metadata to share with the IdP use the URL: \//saml2/service-provider-metadata/SAML ## Full example YAML configuration Below is an example of all the available configuration keys for SAML, with no values supplied except where stated: ``` server: servlet: session: cookie: same-site: none secure: true spring: security: saml2: relyingparty: registration: SAML: entity-id: signing: credentials: - private-key-location: certificate-location: decryption: credentials: - private-key-location: certificate-location: assertingparty: metadata-uri: valsightSamlProperties: loginSuccessfulUrl: userProfileMapping: username: email: fullName: groupsAttribute: mandatoryAttributes: #example value group: groupName ``` ## Logging To log more details you can set logging level to DEBUG for the following packages: * `com.valsight.authentication` * `com.valsight.authentication.saml` * `com.valsight.services.authentication.SSOService` * `org.springframework.security` * `org.springframework.security.saml2` * `org.opensaml` * `org.opensaml.saml` * `org.springframework.web.client` Set the log level to DEBUG ## Reverse proxy configuration If the application is running behind a reverse proxy it will be required to configure the reverse proxy such that the SAML authentication flow can be performed A guide to doing this can be found here: [Reverse Proxy](/reverse-proxy/) --- # Scale-out with load balancer URL: https://docs.valsight.ai/scale-out-with-load-balancer/ Description: How to scale out Valsight servers behind a load balancer for on-premise installations. You can run multiple Valsight servers in parallel. When implementing such a setup, contact support for assistance. *Important: Only applicable for On-Premise installations.* ## (A) Typical trial setup * First setup with a local database, no encryption and no HTTP compression. ## (B) Standard production setup * Reverse Proxy for HTTPS, e.g. Apache, see the [On-Premise Installation Guide](/on-premise-installation-guide/) for an example config file. * GZIP Compression between browser and proxy server * Access to a remote database via SSL as described in [On-Premise Installation Guide](/on-premise-installation-guide/) ## (C) Scale-out setup *Important: The scale-out scenario is not yet certified for self-service implementation. Contact Valsight support, we are happy to assist.* * Run multiple instances of the backend to provide more simulations to a growing amount of users. * Contact Valsight Support to learn details about configuration of the load balancer and config settings for the database. --- # Scenario Bridges URL: https://docs.valsight.ai/scenario-bridges/ Description: A scenario bridge explains the difference between two or more scenarios, broken down by assumption, line-item or dimension. A scenario bridge explains why two or more scenarios differ. It steps from one scenario's value to the next through the individual effects that separate them, all within one time period. ## What it is Each scenario in the chart gets its own sum bar, and the steps in between account for the gap. What those steps represent is your choice: the assumptions that differ, the line-items behind them, or the levels of a dimension such as region or product. ![A scenario bridge stepping from one scenario's value to another through the effect of each assumption](./images/5285838946.png) The staircase shape is what the chart editor calls a **waterfall chart**. A [time bridge](/time-bridges/) uses the same shape to explain a difference between periods rather than between scenarios. ## When to use it * You need to explain why the realistic case lands below the plan. * You want to show which assumptions are actually driving a gap, and which are noise. * You want that gap broken down by region or product rather than by assumption. Use a **[time bridge](/time-bridges/)** instead when the two values you are comparing are two points in time within a single scenario. ## Configuration ### Create the bridge 1. Click the **Chart** button in the upper right corner of a worksheet. 2. Select **Scenario Bridge** in the chart selection. ![Scenario Bridge in the chart type selection](./images/5285642297.png) 3. Select the node to visualize. 4. Select two or more scenarios to compare. 5. Select how the difference should be broken down: by assumptions, by line-items or by a dimension. 6. Select the time period to show. ### Change it afterwards | Setting | What it does | | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Node** | The node whose data the bridge shows. Change it in the chart editor at any time. | | **Scenarios** | Which scenarios appear. Each one you add gets its own sum bar. | | **Configure Axes** | Puts line-items, dimensions or assumptions on the axis. An assumption bridge starts with **Years** as the data series and **Assumptions** on the x-axis. A bridge broken down by a dimension starts with **Scenarios** as the data series instead. | | **Orientation** | Under **Bridge Settings**. Draws the bars horizontally or vertically. | | **Show scenario values** | Under **Bridge Settings**. Draws the start and end scenario as their own sum bars around the effects, and turns on the red and green coloring of the deviations. Switch it off and only the effects in between remain. | | **Show scenario assumption details** | Under **Bridge Settings**, and only for a bridge that steps by assumption. When a shared scenario is used as an assumption, this breaks it out into its own assumptions instead of showing it as one combined bar. | ![The Configure Axes dialog for a scenario bridge](./images/5285740602.png) ### Break the difference down by dimension Instead of assumptions or line-items, the steps can be the levels of a dimension, so the gap is explained by region, product or any other dimension in the model. ![A scenario bridge whose steps are dimension levels rather than assumptions](./images/5752487943.png) There are two ways in, depending on whether the chart exists yet: * While creating the chart, select the dimension as a delta in the configuration wizard. ![Selecting a dimension as a delta in the bridge configuration wizard](./images/5752356871.png) * On an existing chart, choose the dimension in the axis configuration. ![Choosing a dimension in the axis configuration of an existing bridge](./images/5752160274.png) Either way, **Enable levels as deltas** has to be switched on for the levels to be drawn as steps. ![The Enable levels as deltas setting](./images/5752553480.png) ### Show line-item variants The Assumptions dimension carries two separate levels, and picking the wrong one is the usual reason variants do not appear: * **Assumptions - Line Items** gives one step per line-item. The variants of a line-item are folded into it. * **Assumptions - Line Item Variants** gives one step per variant. So to break the difference down by variant, put **Assumptions - Line Item Variants** on the axis in **Configure Axes**. A step carries both the line-item name and the variant name, as `Line-item | Variant`, only when that line-item has more than one variant *and* **Group assumption effects** is off. Otherwise the step carries the line-item name alone. ## Good to know * **Every scenario you add is another sum bar.** A bridge across four scenarios is four sum bars with effects between each pair, which gets wide quickly. Two or three read best. * **Dimension steps need Enable levels as deltas.** Without it the levels are drawn as ordinary values rather than as steps, which is the usual reason a dimension bridge looks wrong. * **The steps do not have to be effects at all.** Put **nodes** on the axis instead and you get a plain build-up, for example revenue and costs stepping down to gross profit. * **A long bridge can be shortened by grouping.** Netting an assumption's removed and added contributions into a single bar often makes the chart readable again. See [Grouping Assumption Effects](/grouping-assumption-effects-in-bridges/). * **Assumptions can explain themselves on hover.** Give an assumption a description and switch on the tooltip setting. See [Showing assumption descriptions](/assumption-effects/#showing-assumption-descriptions). * **A trailing `*` on an assumption means its effect is inverted.** The assumption is active in your start scenario but not in your end scenario, so the bar shows what removing it is worth, which points the opposite way from what you may expect. The chart prints a footnote saying so. These bars appear only while **Group assumption effects** is off. See [Grouping Assumption Effects](/grouping-assumption-effects-in-bridges/). ## Related * [Time Bridges](/time-bridges/): the same staircase, explaining a difference between periods. * [Assumption Effects](/assumption-effects/): how each effect is calculated, and how to show descriptions on hover. * [Grouping Assumption Effects](/grouping-assumption-effects-in-bridges/): net an assumption's removed and added contributions into a single bar. * [Bridges](/bridges/): both bridge types and the settings they share. --- # Scenario Colors URL: https://docs.valsight.ai/scenario-colors/ Description: - Scenarios can be colored to better trace their influence on your simulations Scenarios can be colored to better trace their influence on your simulations. Assigned colors are represented in created charts and tables, and can also be used to improve the appearance of your Scenario Manager, Assumption Groups, the Workspace, and Charts. ## Coloring scenarios Coloring scenarios serves different purposes. It allows you to increase clarity. By assigning specific colors to your scenarios, their impact on charts and tables becomes more visible. That allows you to quickly identify their influence on simulation data. Additionally, you can improve the readability of your visualizations by combining specific scenarios with recurring colors. ## Increasing clarity If you assign a color to a specific scenario, that scenario will be represented in the same color in data visualizations in your Worksheets. Graphs and their respective legends will display the assigned color for the scenario, allowing a faster analysis of its role in your simulations. ![image2021-12-2\_17-30-19.png](./images/5094210893.png)![image2021-12-2\_17-33-26.png](./images/5094210882.png) ## Additional coloring information Common examples are green for "best" cases or red for "worst" cases, with neutral colors such as blue for "standard" cases. An important aspect of proper color coding is consistency. By using the same colors for equivalent scenarios, especially across different projects, you can help other users understand your workspace and the presentations generated from it. The Valsight default is a collection of high-contrast colors, to allow an effective highlighting of information. It is possible to implement a custom color palette. This enables you to represent your data in accordance with your corporate identity. See details at [Editing the color palette](/editing-the-color-palette/) --- # Scenario Manager URL: https://docs.valsight.ai/scenario-manager/ Description: Learn what the Scenario Manager is, what it does, and which parts of Valsight it ties into. Learn what the Scenario Manager is, what it does, and which parts of Valsight it ties into. * The Scenario Manager is the central control hub of all simulations * It contains scenarios, assumptions, and line-items and allows you to modify data to build simulations * It builds upon the base model and stores changes to its inputs * You can im- and export scenarios, assumptions, and line-items via the Scenario Manager * The Scenario Manager can be added as a tile in any worksheet ## Overview The Scenario Manager is the core part of Valsight. Using the Scenario Manager, you can edit the data of assumption groups and line-items, and activate and deactivate these line-items. The active line-items are then considered in the calculation of a scenario. By modeling your business with Valsight and connecting data to the nodes in your model structure, you create a consistent baseline for the simulation of possible changes. You can then calculate changes onto this baseline by simulating assumptions and measures as a delta on top of that baseline. Using the simulated data, you can subsequently generate [visualizations](/creating-charts/) in the form of charts and tables in your workspace, allowing you to present the data to others in an apprehensive and readable format. ![Scenario Manager beschriftet.png](./images/5094230425.png) A view of the Scenario Manager with: 1. Scenarios on top of the Scenario Manager 2. An assumption group consisting of several line-items 3. A line-item 4. The scenarios columns, where line-items (and their variants) and assumptions are assigned to scenarios To use the Scenario Manager, enter the "Simulating" page from the navigation bar and select one of your [workspaces](/workspaces/). From there, you can access the Scenario Manager from any worksheet by using the "Scenario Manager" button in the upper right corner of the screen. ![Getting to Scenario Manager.gif](./images/5094230421.gif) ## Controlling simulations You can simulate several kinds of changes. These include absolute or relative changes to the base values of your data, as well as [directly setting data](/line-item-data-details/) to a specific value. You can also[link sliders](/sliders-in-the-scenario-manager/), to modify your simulation data dynamically. ## Scenarios Scenarios in Valsight are changes to data based on possible strategic actions of your company (measures) or changes in the business environment (assumptions). Each assumption and measure is represented as a delta on your baseline. Scenarios are created with the “+” icon in the upper right corner of the Scenario Manager. Everything you can then do to one sits in its three-dot menu, in the scenario's column header: | Menu entry | What it does | | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Edit** | Opens the “Edit Scenario” dialog on its **Settings** tab: the scenario's name, description, the data baseline it is based on, and its [color](/scenario-colors/) in charts. A second tab, **Variables**, activates [project variables](/project-variables/) for this scenario. | | **Duplicate** | Opens “Duplicate Scenario”, where you give the copy its own name, description and color. | | **Share** | Publishes a snapshot of the scenario for other users. See [Sharing Scenarios](/sharing-scenarios/). | | **Versioning…** | A submenu holding **Save Version** and **Show History**. See [Scenario Versioning](/scenario-versioning/). | | **Download active Assumptions** | Exports this one scenario as an xlsx file, with extra sheets for the assumptions and variables active in it. | | **Move Left**, **Move Right** | Moves the scenario one column along. Greyed out at either end of the row. | | **Delete** | Deletes the scenario. | > **The three-dot menu is not always there.** It is hidden in presentation mode, in a drill-down, and on a workspace you can only read. If a scenario has variables overwritten in it, a round “Changed Variables” tag appears under its name with the number of them. Clicking that tag opens the same “Edit Scenario” dialog directly on its Variables tab. ![image-20240124-092436.png](./images/5350653960.png) ## Assumptions Assumptions are collections of line-items. They group line-items into more manageable clusters, usually representing multiple similar or related changes to your base drivers. Assumptions possess many of the same edit functionalities as scenarios, like the ability to be duplicated or to use saved, previous versions of them. Common examples of assumptions are "Staff assumptions" or "Market Developments". These represent collections of driver changes, that influence a specific sector of your business model. ## Line-Items Line-items are the instance of change to your base model. They affect a single node and can filter its content to apply even more specific changes. By creating and combining line-items, you can build your simulation on a granular level. Line-items contain changes to the values of a node. These changes are stated either as a relative change (%) or as absolutes. Additionally, a line-item can consist of [multiple variants](/line-item-variants/), which are alternative versions of the same line-item based on the same node. This can be useful for certain exclusive assumptions, like “pessimistic” or “optimistic” market growth. Like assumptions, line-items can be duplicated. ## Additional functions and tools ### Im- and exporting data The Scenario Manager supports the [im- and export of uploaded data](/data-upload-import-export-overview/), simplifying the creation and adjustment of scenarios, assumptions, and line-items. You can upload XLSX files to base your simulation’s base data and scenarios on, or download scenarios, assumptions, and line-items to use with other software or workspaces. If you want to learn more about this, we have an [in-depth guide on the im- and export of data](/data-upload-import-export-overview/). ### Interfaces The Scenario Manager supports the use of common software interfaces to automate the creation and configuration of scenarios, assumptions, and line-items. Valsight supports common data formats/interfaces such as XLSX, OData, or JDBC for Base Data, as well as JSON or CSV for importing and exporting processed data and visualizations. Every part of the Valsight server can be accessed using a REST-based API. In order to simplify such ventures, Valsight ships a tool to handle cookie authentication and provide useful methods for accessing parts of it. A dedicated guide to the Valsight API client[can be found here](/valsight-api-client/). For further information on the im- and export of data to and from Valsight, please refer to the [Importing/Exporting Files/Data Upload documentation page](/data-upload-import-export-overview/). ### Versioning The Scenario Manager allows you to save versions of scenarios and assumptions. They can later be restored to the state they were saved in. This proves useful for experimentation, as well as for optimization efforts, as it allows users to test different versions of a scenario or assumption by quickly switching between different versions. If you want to learn more, we have [a detailed guide on how and why to create and restore versions of assumptions](/assumption-versioning/). For information on the versioning of scenarios, please [look here](/scenario-versioning/). ### Creating templates Another key feature of Valsight is the creation of templates and their subsequent use through the template manager. Creating templates can significantly reduce the necessary time to set up your simulations and enables you to comfortably reuse assumptions with other workspaces based on the same model. If you want to know more about the creation of templates, take a look at the [template manager page](/template-manager/). ### Using workflows Valsight offers the option of using workflows with your Scenario Manager. Workflows are a useful tool for organizing processes and maintaining control over the tasks at hand. Using workflows enables you to structure processes into several smaller increments, or steps, which can then be used as a guideline for completing tasks. This also enables collaboration between different users working on a project simultaneously. A dedicated guide on workflows, and how to create and use them effectively,[can be found here](/workflows/). ## Related * [Assumptions & Line-Items](/assumptions-line-items/) * [Scenarios](/scenarios/) --- # Delta Comparisons URL: https://docs.valsight.ai/scenario-time-or-dimension-level-comparison-delta/ Description: Add a delta comparison to a table so it shows the change between two scenarios, periods or dimension levels, and pick the method that suits your data. A delta comparison shows the change between two data points in a table: between two scenarios, two periods, two dimension levels such as two products, or two nodes. ## Overview Comparisons are added to an existing table in the chart editor. Which method you choose matters more than it looks, because two of them disagree whenever the base value is negative. ## Adding a comparison 1. [Create a table chart](/creating-charts/). Setting **Nodes** as rows, with **Years** and **Scenarios** as columns, is a good starting point. 2. In the chart editor, add a comparison. Pick the two values to compare, then set the **Calculation type**. 3. For a **Delta**, which is labeled **YoY** when you compare years, choose one of the three delta methods from the table below. **CAGR** is a calculation type of its own and is offered only when the two values are years. The same comparison can be built across time, across dimension levels, for example sales for different products, and across nodes. ## Editing existing comparisons Once a table has at least one comparison, you can edit or remove comparisons in place. 1. In the chart editor, open **Edit Comparisons**. The button appears only when the table already has a comparison. 2. The dialog lists every comparison on the left. Select one to load its full configuration on the right, pre-filled with its current settings. 3. Rename or reconfigure the comparison. You can edit as many comparisons as you like in the same session. 4. To remove a comparison, use the trash icon next to it in the list. 5. Click **Save** to apply all your changes at once. **Cancel** discards them; if you have unsaved changes, you are asked to confirm first. Comparisons keep their position in the chart, and **Save** stays disabled until every edited comparison is valid. ## Comparison methods | Method | What it calculates | Formula | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | | **Absolute** | The plain difference between the two data points. | `second value - first value` | | **Relative, default** | The relative percentage change, carrying the sign of the absolute change. | `abs((second value / first value) - 1) × signum(second value - first value)` | | **Relative, simple** | The plain percentage difference. | `(second value / first value) - 1` | | **CAGR** | The compound annual growth rate: the average growth needed over the given years to reach the second value. Offered only when the two data points are years. | `abs(abs(second value / first value) ^ (1 / years) - 1) × signum(second value - first value)` | ## Choosing between the two relative comparisons On a positive base the two agree. They diverge on a negative base, and that is the whole reason the default exists. Going from **-100** to **-50** is an improvement of 50: * **Relative, simple** returns `(-50 / -100) - 1 = -0.5`, so **-50 %**, which reads as a decline. * **Relative, default** takes the size of that change and applies the sign of the absolute change: `abs(-0.5) × signum(50) = +0.5`, so **+50 %**. Use the **default** relative comparison unless you have a specific reason not to. The simple one is only safe when every base value is positive. ## Related * [Formatting Charts](/chart-configuration/): sorting, scales and table styles. * [Data Display in Charts and Tables](/data-display-in-charts-and-tables/): choosing what a table shows, and at which level of aggregation. * [KPI Charts](/kpi-charts/): a comparison shown as a single figure rather than a table column. --- # Scenario Versioning URL: https://docs.valsight.ai/scenario-versioning/ Description: On this page you will find a general description of scenario versions as well as a tutorial on how to create them. On this page you will find a general description of scenario versions as well as a tutorial on how to create them. Different Scenario Versions can be compared in Charts, and they can be deleted. Restoring, however, is only possible for [Assumption Versions](/assumption-versioning/). ## Sharing a scenario Whenever you *Share* a Scenario of which you haven't created a version, Valsight will automatically create one once its shared. This Version will have the name and description you entered when sharing the scenario. ![Share Scenario v2.18.png](./images/5094194138.png)![Screenshot 2019-04-10 at 18.53.51.png](./images/5094194673.png) ## Changing assumptions Whenever you change an Assumption or Line Item that is part of the scenario and save or share said scenario, Valsight will automatically create a new [Assumption Version](/assumption-versioning/). This Version will have the name and description you entered when sharing or saving the scenario. ## Create a new scenario version First, open the *Scenario Manager* and select the *Options* (3 dots) next to the Scenario you want to version. Then select *Versioning → Save Version*. ![starting\_point.png](./images/5094191363.png) Now you can name your Scenario Version, add a description (optional) and *Confirm* to save. The name is optional and does not have to be unique, but it must not contain special characters. Versions are told apart by the version number Valsight assigns, shown next to the name as ‘Scenario v2 (name)’. ![scenario\_version\_creation\_ui.png](./images/5094191358.png) ## Editing scenario versions Open the *Scenario Manager* and select the *Options* (3 dots) next to the Scenario of which you want to restore a previous version. Now select *Versioning → Show History* to open the version history of the selected Scenario. Here you can decide, if the version should be an option to be compared in your charts. See Use Scenario Versions in Charts to learn more. ![Screenshot 2019-04-10 at 18.59.23.png](./images/5094194708.png) ## Deleting scenario versions Open the version history the same way, select the scenario version(s) that you would like to delete, then hit the "Delete" button at the bottom of the dialog: ![Screenshot 2019-04-10 at 19.02.29.png](./images/5094194703.png) There are currently several outcomes of this operation: 1. You cannot delete a scenario version that is being "shared" (you need to manually "unshare" it before deleting it) ![Screenshot 2019-04-10 at 19.04.58.png](./images/5094194698.png) 2. If deleting a version will trigger the automatic deletion of other versions that refer to it (but not used anywhere else), you will be prompted a list of "affected versions". All of these versions (including the ones you are selected) will be removed after you confirm the action: ![Screenshot 2019-04-10 at 19.12.03.png](./images/5094194693.png) tips: you can mouse-hover on the items to see more details (i.e. which original scenario it is, when it was created, etc.) 3. If deleting a version should trigger the automatic deletion of other versions that refer to it, but these versions are still shared, or otherwise used somewhere else in the project, you will be shown a list of "version dependencies", from which you can take manual actions before you can come back and retry deleting the version you initially selected: ![Screenshot 2019-04-10 at 19.17.56.png](./images/5094194688.png) tips: you can mouse-hover on the items to see more details (i.e. which original scenario it is, when it was created, etc.) **ENABLE SCENARIO VERSIONS TO BE USED IN CHARTS** To be able to select your Scenario Version in a chart, you first need to check *Used in charts* in your Scenario Version History. ![Scenario Version use in Charts charts v2.18.png](./images/5094216007.png) ***Insert Scenario Versions into Charts*** All Scenario versions that are marked as *Used in charts* will now be selectable in the [chart configuration menu](/creating-charts/). ![scenario\_version\_selectable\_in\_chart\_config v2.18.png](./images/5094215798.png) Congratulations, you can now compare different scenarios versions in your charts. ![scenario\_versions\_in\_charts.png](./images/5094216016.png) > Learn more about [Chart Types](/chart-types/) and [How to Create Charts & Tables](/creating-charts/). --- # Scenarios URL: https://docs.valsight.ai/scenarios/ Description: Scenarios describe possible future developments of your business. They combine assumptions and measures to explore how outcomes change under different condit… Scenarios describe **possible future developments** of your business. They combine assumptions and measures to explore how outcomes change under different conditions. ## Why it is relevant * Enables structured thinking about alternative futures * Allows comparison of strategic options and external developments * Keeps planning discussions transparent and consistent * Supports decision-making under uncertainty ## How it works A scenario represents a **set of changes applied on top of a baseline**. Each scenario: * Is always based on one baseline * Combines multiple assumptions and measures * Applies all changes as deltas to the baseline values * Represents one coherent view of a possible future Because all scenarios share the same model structure, results remain comparable across scenarios. ![Scenarios\_SM.png](./images/6664192010.png) ## Setup Scenarios are created and managed in the Scenario Manager. When creating a scenario, you define which baseline it builds on. Additional settings such as naming or visual identification help distinguish scenarios later on. ## Using the feature * Use scenarios to model different strategic or environmental outcomes. * Combine assumptions to form realistic future narratives. * Compare scenarios to understand sensitivities and trade-offs. * Version scenarios as planning evolves. ## Access & permissions Scenarios follow workspace permissions. Opening the Scenario Manager only needs view access. Creating and editing scenarios needs **Full Access** on the workspace *and* at least a Simulator user type. See [Licenses, User Types & Access Management](/licenses-user-types-access-management/). ## FAQ **What is the difference between a baseline and a scenario?** A baseline defines the core logic and base values. A scenario applies changes on top of that baseline. **Can a scenario include multiple assumptions?** Yes. Scenarios typically combine several assumptions and measures. **Can scenarios be versioned?** Yes. Scenarios support versioning to track planning changes over time. **Do scenarios change the model structure?** No. They only change values, not the underlying model. **Can I rename a scenario that is part of a workflow?** Scenarios are attached to a [workflow](/workflows/) by their name. Renaming one unlinks it from the workflow, and giving another scenario the exact name of a workflow scenario links that one in instead. Valsight asks you to confirm before saving such a rename. **Can scenarios overwrite my base data?** No. Scenarios apply changes on top of the base data and are only used to model possible future developments. ## Related * [Working with different Model Baselines](/working-with-different-model-baselines/) * [Assumptions](/assumptions/) * [Line-items](/line-items/) --- # SCHEDULEPROJECTS URL: https://docs.valsight.ai/scheduleprojects/ Description: Combines project KPI blueprints over time with timing information that defines when projects start. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **SCHEDULEPROJECTS** function **combines project KPI blueprints** over time with timing information that defines when projects start. Use this function when you want to place reusable project blueprints onto actual start periods based on a timing node. For a worked example, see the training model T02 Hochlaufkurven in [Trainingsmodelle - Modelle](/hochlaufkurven/). ## Syntax `SCHEDULEPROJECTS('ProjectKPI', 'TimingNode' [, "TimeLevel"])` ## Parameters | Parameter | Description | Type | Required | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | | **ProjectKPI** | Contains the project KPI data over time (e.g. revenue). | Node reference | Yes | | **TimingNode** | Contains data for the starting points of projects. This node is typically a simulation node used to simulate different starting points for projects. | Node reference | Yes | | **TimeLevel** | Specifies the time level (`"Month"`, `"Quarter"`, `"Year"`) in which the offset is given in the ProjectsNode. If this parameter is omitted, `ProjectKPI` is assumed to be on the lowest time level in the TimingNode. | Level name | No | ## Examples ### Scheduling project blueprints by start period This example shows how reusable project KPI blueprints are placed onto actual years based on a timing node. A small and a large project each span two years and start in different periods. **Input node:** `'ProjectKPI'` | Project | Sequence | Value (Revenue) | | ------------- | -------- | --------------- | | Small Project | 1 | 500 | | Small Project | 2 | 700 | | Large Project | 1 | 8,000 | | Large Project | 2 | 9,000 | The Sequence column shows that the Small Project generates 500 of revenue in the first year and 700 in the second year. Instead of year, month or quarter can also be used by changing the time column in the TimingNode or by specifying the TimeLevel parameter. **Input node:** `'TimingNode'` | Project | Year | Value (Number of projects) | | ------------- | ---- | -------------------------- | | Small Project | 2025 | 2 | | Small Project | 2026 | 5 | | Large Project | 2025 | 0 | | Large Project | 2026 | 10 | Here we specify how many projects start when. Two Small Project items start in 2025, while five Small Project and ten Large Project items start in 2026. **Formula:** `SCHEDULEPROJECTS('ProjectKPI', 'TimingNode')` | Project/Year | 2025 | 2026 | 2027 | 2028 | | ------------- | ------------ | -------------- | -------------- | ---- | | Small Project | **1,000**(2) | **3,900**(2+5) | **3,500**(5) | 0 | | Large Project | 0 | **80,000**(10) | **90,000**(10) | 0 | ## Related | Function | When to use instead | | ------------------ | -------------------------------------------------------------------------------------------------------------------- | | [SHIFT](/shift/) | When you already have values and only need to move them along a time level by a defined offset. | | [EXPAND](/expand/) | When you first need to create the target shape or add missing level combinations before applying further time logic. | --- # Secure Statistics Collection URL: https://docs.valsight.ai/secure-statistics-collection/ Description: Statistics about the usage of Valsight help us to create better features, improve existing functionality and identify and fix potential technical problems. Statistics about the usage of Valsight help us to create better features, improve existing functionality and identify and fix potential technical problems. Our statistics collection mechanism does not track any personal data and only collects anonymized data that does not allow to track any actions of individual users. It is secure and follows the principle of data avoidance and allows to include customers in the cloud and on-premise without the use of any third party software. ## Collected events The following events are currently collected. | Area | Event | Measuring | Introduced in version | | ---------------- | --------------------------------------------------------------------------------------------------- | ------------- | --------------------- | | App | App is loaded | User activity | 4.1.0 | | App | List loading and opening (project, model, workspace), including loading time and type of list | Performance | 4.5.0 | | App | NPS value, including closing the NPS dialog unanswered | User activity | n/a | | Project | Loading time project creation | Performance | n/a | | Project | Loading time project deletion | Performance | n/a | | Project | Loading time project duplication | Performance | n/a | | Model | Model is opened, including loading time | Performance | 4.5.0 | | Model | Validation | Performance | n/a | | Model | Addition, entered via overview, validation | User activity | 5.0.0 | | Model | Creation, deletion, copy and paste, data preview, operation change | User activity | 5.0.0 | | Model | Functions overview is opened | User activity | 5.0.0 | | Workspace | Workspace is opened, including loading time, preparation time and number of sheets and charts | Performance | n/a | | Workspace | Chart is loaded, including loading time | Performance | 4.4.0 | | Workspace | Addition, addition from template, copy, export, movement, saving as template, saving as copy | User activity | 5.0.0 | | Workspace | Presentation is added | User activity | 5.0.0 | | Workspace | Workspace is added | User activity | 5.0.0 | | Workspace | Sheet is added, deleted or duplicated | User activity | 5.0.0 | | Workspace | Tile is deleted | User activity | 5.0.0 | | Workspace | State is discarded | User activity | 5.0.0 | | Workspace | Export as Excel | User activity | 5.0.0 | | Workspace | Manual and automatic refresh | User activity | 5.0.0 | | Workspace | Entered via overview | User activity | 5.0.0 | | Workspace | Save (and opened) | User activity | 5.0.0 | | Workspace | Save new changes | User activity | 5.0.0 | | Scenario Manager | Line-item is added | User activity | 5.0.0 | | Scenario Manager | Scenario is added | User activity | 5.0.0 | | Scenario Manager | Assumptions (addition, activation, deactivation) | User activity | 5.0.0 | | Scenario Manager | Clicking add scenario assumption item button | User activity | 5.0.0 | | Scenario Manager | Variants (creation, deletion, activation) | User activity | 5.0.0 | | Presentation | Print | User activity | 5.0.0 | | Presentation | Preview | User activity | 5.0.0 | | Presentation | Opening Scenario Manager | User activity | 5.0.0 | | Settings | Groups (creation, deletion) | User activity | 5.0.0 | | Settings | Item (addition, deletion) | User activity | 5.0.0 | | Settings | Group and axis (change scale, set min and max values and digits, activate and deactivate inversion) | User activity | 5.0.0 | ## Metadata Each collected event includes the following metadata. | Field | Description | Example | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | | appVersion | Version of the application | 4.3.1 | | timestamp | Time the event was collected | 2020-01-01T12:00:00.150Z | | event | Event type (see Collected events above) | initActivityLogging | | instance | Name of the instance | valsight | | instanceType | Whether the instance is a customer instance or an internal instance | customer | | sessionIdentifier | Anonymized hash of a session, individual sessions cannot be associated to users | f350a391-891a-4271-a69c-e739eecc11ab | | monthlyUserIdentifier | Anonymized hash to calculate unique users, the hash is changed on a monthly basis and only included for initial login events, so that it does not allow to track users across sessions. | -571141652 | --- # Security audit log URL: https://docs.valsight.ai/security-audit-log/ Description: The following page explains the different events that are logged when using the 'Security audit log'. The following page explains the different events that are logged when using the 'Security audit log'. A 'Security audit log' can be used to **track relevant activities** performed in Valsight. The relevant files to activate the security audit log are located in the Valsight settings (navigation bar) → Metric and Logs → Download 'Valsight Security Audit Log Files (ZIP)'. ## What is logged? Each event has the following aspects that are logged via the security audit log: | Header | Description | | ----------------- | ---------------------------------------------------------------------------- | | Time | When the event occurred | | User | The logged in user who caused the event | | Object type | On what object type has the vent occurred (Group. User, Project, Model, ...) | | Object key | The exact object on which the event occurred | | Project | The exact project in which the event occurred | | Action type | Which event occurred | | Action parameter1 | Additional info if all other headers aren't enough | | Action parameter2 | Additional info if all other headers aren't enough | | Action parameter3 | Additional info if all other headers aren't enough | Precise details about newly logged objects and what we log on them: | Domain Object | Action Type | Detail | | ---------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | AssumptionGroup | Property change | Name | | DataParameter | Deleted | Except when deleted by deleting a workspace, model or project | | DataParameter | Property change | Everything except description | | DataParameterVariant | Line-item data change | N/A | | DataParameterVariant | Delete | Except when deleted by deleting a workspace, project or data parameter | | Dimension | Created | N/A | | Dimension | Deleted | Except when deleted by deleting a project | | Dimension | Property change | Everything except description | | ExternalDataSource | Deleted | Except when deleted by deleting a project | | Level | Created | N/A | | Level | Deleted | N/A | | Level | Property change | Everything | | Model | Property change | Only modelConfig changes are logged | | Model | Deleted | Except when deleted by deleting a project | | Node | Property change | Everything except description and displayConfig | | PlanningWorkflow | Deleted | Except when deleted by deleting a project | | ProjectVariable | Created | N/A | | ProjectVariable | Property change | Both name and value | | ProjectVariable | Deleted | Except when deleted by deleting a project | | ScenarioExportTemplate | Deleted | Except when deleted by deleting a project | | SimulationRun | Property change | The values name, baseline and parentSimulationRun | | SimulationRun | Deleted | Except when deleted by deleting a project or workspace | | SimulationRunVariable | Created | N/A | | SimulationRunVariable | Property change | Includes the value of the original. This also logged when we create a variable override, to log the changes between the project’s and scenario’s values. | | SimulationRunVariable | Deleted | Except when deleted by deleting a project, model, workspace or scenario | | SimulationWorkspace | Property change | Everything in the simulationConfig | | SimulationWorkspace | Deleted | Except when deleted by deleting a project | | WorkflowStep | Deleted | Except when deleted by deleting a workflow or project | ## Logged events #### Add+Create/Remove+Delete/Change | Event | Action type | Action Parameter 1 | Action Parameter 2 | Action Parameter 3 | Added in Version | | --------------------------------------------------------------------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ----------------------- | ---------------- | | Adding permissions | Added permission | For which user/group is the permission added | N/A | N/A | Since beginning | | Adding a role to the user or group | Added role | name of the role | N/A | N/A | Since beginning | | Adding an user to a group | Added user to group | user | N/A | N/A | Since beginning | | Creating an user or group | Created | 'preAuth', 'SAML', 'openIdConnect' or no parameter | N/A | N/A | Since beginning | | Create project variables | Created | ‘value' | variable value | N/A | 5.8.0 | | Update project variables | Property change | parameter type either ‘name’ or ‘value’ | parameter old value | parameter new value | 5.8.0 | | Scenario variable | Created | N/A | N/A | N/A | 5.8.0 | | Update scenario variable | Property change | ‘value’ | Value of project variable the scenario variable is overriding | scenario variable value | 5.8.0 | | Delete scenario variable | Deleted | N/A | N/A | N/A | 5.8.0 | | Dimension row added | Property change | dimRowAdded | name of each level and the value added to the level (including extended levels) | N/A | 5.8.0 | | Removing permissions | Removed permission | For which user/group is the permission removed | N/A | N/A | Since beginning | | Removing a role from the user or group | Removed role | name of the role | N/A | N/A | Since beginning | | Removing user from the group | Removed user from the group | user | N/A | N/A | Since beginning | | Deleting an user or group | Deleted | N/A | N/A | N/A | Since beginning | | Node deletion | Deleted | names of the node, its model and project | N/A | N/A | 4.0.0 | | Model deleted | Deleted | name of the model, name of the project space | N/A | N/A | 5.8.0 | | Workspace deleted | Deleted | the name of the project space it belongs to | N/A | N/A | 5.8.0 | | Data source deleted | Deleted | the name of the project space it belongs to | N/A | N/A | 5.8.0 | | Workflow deleted | Deleted | the name of the project space it belongs to | N/A | N/A | 5.8.0 | | Submission deleted | Deleted | the name of the project space it belongs to | N/A | N/A | 5.8.0 | | Dimension deleted | Deleted | the name of the project space it belongs to | N/A | N/A | 5.8.0 | | Templates deleted | Deleted | the name of the project space it belongs to | N/A | N/A | 5.8.0 | | Project variable deleted | Deleted | N/A | N/A | N/A | 5.8.0 | | Scenario variable deleted | Deleted | N/A | N/A | N/A | 5.8.0 | | A line item variant is deleted | Deleted | data parameter variant's key | N/A | N/A | 5.8.0 | | Changing the project or application setting | Changed setting | A detailed description on which setting was changed, what was the previous value and what is the new value | N/A | N/A | Since beginning | | Changing password of the user | Password changed | N/A | N/A | N/A | Since beginning | | Changed data access permissions on a dimension or level (value) | Data permissions | N/A | N/A | N/A | 3.1.0 | | Moving a node | Node changed models | old model | new model | N/A | 4.0.0 | | A line item variant is updated | Line-item data change | N/A | N/A | N/A | 5.0.0 | | A line item was selected or unselected from a scenario | Line item selection | 'selected' or 'unselected' | parameter's key | N/A | 3.1.0 | | A line item variant is ‘selected’ or 'unselected' from being associated with a scenario | Line-item selection | 'selected' or 'unselected' | data parameter variants's key | N/A | 5.0.0 | | User enabled or disabled | Property change | 'enabled' | old value | new value | 3.7.0 | #### Actions by users | Event | Action type | Action Parameter 1 | Action Parameter 2 | Action Parameter 3 | Added in Version | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------- | ----------------------------------------------- | ---------------- | | User creates, deletes or reverts a version | Versioning action | 'versioned', 'shared', 'unshared', 'deleted version' or 'reverted' | optional: the created version or version you are reverting from | optional: workflow's key if it was a submission | 3.1.0 | | User links or unlinks levels | Object linking | 'extended' or 'extension removed' | the key of the level that we extending by or removing extension to | N/A | 3.1.0 | | User removes a value from a level | Property change | 'levelValueRemove' | the value | N/A | 3.1.0 | | User changes a value of a level | Property change | 'levelValueChange' | the value | N/A | 3.1.0 | | User change a parent value of a value | Property change | 'levelValueParentChange' | the value | \ → \ | 3.1.0 | | User renames an object | Property change | 'name' | old name | new name | 3.1.0 | | User changes a property on an object | Property change | name of the property | new value | N/A | 3.1.0 | | User moves a line item from one group to another | Property change | 'movedFromGroup' or 'movedToGroup' | the group | N/A | 3.1.0 | | User does an action on a debug page | Special admin action | action name | HTTP method used | N/A | 3.1.0 | | User logged in | User logged in | 'preAuth', 'SAML', ' openIdConnect' or no parameter | N/A | N/A | Since beginning | | User failed to login | Failed login | User that failed to login | empty or ''credentials OK - user blocked' or 'credentials OK - IP blocked' | N/A | Since beginning | | User uploads a file that may change a DS or dimension table | File upload | N/A | N/A | N/A | 3.1.0 | | User downloaded log files | Log download | 'server.log' or 'securityAudit.csv' | N/A | N/A | 3.1.0 | | User was denied access to modify data | Data permissions write denied | Level value | Data permission class name | N/A | 3.8.8 | | User performed an action that caused time dimension data to be regenerated | Time dimension change | \[\...\]...Q\ | N/A | N/A | 3.1.0 | | User saved or discarded the workspace | Workspace save action | 'save', 'discard', 'saveAs' | N/A | N/A | 3.1.0 | | User changed data of a line item | Line item data change | N/A | N/A | N/A | 3.1.0 | | User changed data of a line item variant | Line item data change | N/A | N/A | N/A | 5.0.0 | | User changes line item name | Property change | ‘name’ | old name | new name | 5.0.0 | | User changes line item slider minimum | Property change | ‘sliderMin’ | old value | new value | 5.8.0 | | User changes line item slider maximum | Property change | ‘sliderMax’ | old value | new value | 5.8.0 | | User changes line item slider step | Property change | ‘sliderStep’ | old value | new value | 5.8.0 | | User created new API key | API key created | N/A | N/A | N/A | 3.6.0 | | A user’s session ends either through an explicit logout or an inactivity timeout. **NOTE:** If the session ends to an inactivity logout it can take 30 - 40 minutes for it to be registered as having expired in the log. Thus the time of the log entry can not be seen as the time the session actually expired. | User logged out | Username of the user associated with the session | N/A | N/A | 5.8.0 | | User changed the dimension table from a data source table | Property change | ‘dimensionTable’ | ‘autoDim’ | Audit key of the data source table | 5.8.0 | #### Block events | Event | Action type | Action Parameter 1 | Action Parameter 2 | Action Parameter 3 | Added in Version | | ----------------------------------------------------------------------------- | -------------- | ------------------------- | ------------------ | ------------------ | ---------------- | | User blocked, due to too many unsuccessful consecutive logins | User blocked | 'unsuccessful logins' | N/A | N/A | Since beginning | | Blocked user manually unblocked | User unblocked | 'on boot' or no parameter | N/A | N/A | Since beginning | | Blocking IPs due to too many unsuccessful consecutive logins from the same IP | IP blocked | The blocked IP | N/A | N/A | Since beginning | #### File export/import | Event | Action type | Action Parameter 1 | Action Parameter 2 | Action Parameter 3 | Added in Version | | -------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------- | ------------------------- | ------------------ | ---------------- | | Chart exported | File export | 'Formatted export' or 'Raw export' | N/A | N/A | 5.8.0 | | Workspace Export | File export | 'Formatted export' or 'Raw export' | N/A | N/A | 5.8.0 | | Line item Download Excel | File Export | 'Data parameter download' | DataParameter audit key | N/A | 5.8.0 | | Assumption group Download Excel (a separate log line is made for each line item in the assumption group) | File Export | 'Assumption group download' | AssumptionGroup audit key | N/A | 5.8.0 | | Download excel for all assumption groups (a separate log line is made for each line item in each of the assumption groups) | File Export | 'Bulk workspace download' | Workspace audit key | N/A | 5.8.0 | | Node data preview download | File Export | Audit key of either the Baseline or SimulationRun associated with the data preview | N/A | N/A | 5.8.0 | | Project export | File Export | N/A | N/A | N/A | 5.8.0 | | Tampered project import | Tampered project import | Detailed reason, one of: Missing signature; Signature does not match content; Invalid signature | N/A | N/A | 6.0.0 | #### Others | Event | Action type | Action Parameter 1 | Action Parameter 2 | Action Parameter 3 | Added in Version | | --------------------------------------------------------------------------------- | -------------------------- | --------------------- | ------------------ | ------------------ | ---------------- | | host header poisoning - The supplied host header is not included in the allowlist | Bad Host Header | Actual host header | N/A | N/A | 3.3.0 | | Jdbc / Odata table import | External Datasource import | imported tables names | N/A | N/A | 4.0.0 | --- # Security Configuration URL: https://docs.valsight.ai/security-configuration/ Description: Valsight offers you to set your security configuration individually, to ensure a user and company optimized setting. Valsight offers you to set your security configuration individually, to ensure a user and company optimized setting. First step is to navigate to the respective menu, which is found after selecting the configuration button ![image2019-8-8\_14-57-9.png](./images/5094193840.png). There you choose the item "settings". ![image2019-8-8\_14-53-57.png](./images/5094193925.png) The second section of the following page shows the security settings and offers a range of different guidelines. 1. You can set the blocking time for repeatedly failing logins. ![image2019-8-8\_15-4-44.png](./images/5094193845.png) 2. The number of failed logins before triggering the previous step (1.). ![image2019-8-8\_15-5-55.png](./images/5094193935.png) 3. The time in hours for how long the last failed login is stored in Valsight. ![image2019-8-8\_15-6-54.png](./images/5094193940.png) 4. In case you want to protect your Excel exports, you can add an additional password to the download and export options. ![image2019-8-8\_15-26-52.png](./images/5094191054.png) ## Password settings > The password settings are not relevant if you are using a company-sigle-sign-on solution to login. You have also various options to set up your password settings. You can define digits as mandatory part of a password. ![image2019-8-8\_15-31-48.png](./images/5094191059.png) The same goes for lower case letters, as well as special characters and upper case letters. ![image2019-8-8\_15-37-2.png](./images/5094190939.png) To increase your password security, you can set up the minimum length for passwords. ![image2019-8-8\_15-38-44.png](./images/5094190949.png) You can also define the number of last used passwords, which can not be used for the present one. ![image2019-8-8\_15-40-17.png](./images/5094191074.png) As one of the most common settings, you are also able to define the time (per days) for how long passwords are valid. ![image2019-8-8\_15-42-41.png](./images/5094191069.png) A typical and secure configuration would look as follows. ![image2019-8-8\_15-52-12.png](./images/5094191064.png) ## Data source files / Excel files By default, the original file that are uploaded into the system can also be downloaded again. As those original files are downloaded unmodified, this might be considered a security risk. You can disable the download by setting the respective option "*disableDownloadXLS*". If the option is enabled, the download of data source files is limited to only provide a generated Excel file and not the original. ![Screen Shot 2020-10-23 at 09.14.23.png](./images/5094191653.png) --- # Server Configuration URL: https://docs.valsight.ai/server-configuration/ Description: Typical Setups use a separate reverse proxy as SSL Endpoint instead of the integrated SSL functionality. See Deployment overview. The core server settings for an on-premise installation: session timeout, SSL/TLS, host header restrictions, CSRF prevention, user management and the CORS allowlist. ## Session duration ``` server: sessionTimeout: 5400 ``` ## SSL > Typical Setups use a separate reverse proxy as SSL Endpoint instead of the integrated SSL functionality. See Deployment overview. Generate a key: openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 -name jetty -caname root Make sure the keyAlias matches exactly - it is case sensitive. To check the keystore, you may run keytool(.exe) -list -v -keystore path\to\conf\keystore.p12 ``` server: port: 8443 ssl: keyStore: /certificates/keystore.p12 keyStorePassword: secret keyAlias: jetty ``` ## Restricting host headers It is possible to configure exactly which host headers the HTTP requests are allowed to have. If we don't configure this, the servers accepts all hosts. The server checks the values of 'X-Forwarded-Host' and 'Host' header, where the header 'X-Forwarded-Host' takes priority. If no configured headers match the HTTP header value the servers responds with HTTP status 400. This also happens if the HTTP headers are missing. To configure simply add the property 'hostHeaderAllowlist' to the config.yml, followed by a comma separated list of accepted domains. ``` hostHeaderAllowlist: mydomain1.com:8080, mydomain3.net ``` The domains must be configured to the value that is sent to the server, which may differ from the URL in the browser. ## CSRF prevention By default, the server is configured so that CSRF attacks are prevented by requiring a unique token to be send for form requests. The REST API requires the content type to be application/json. If needed, both security mechanism can be disabled via the *config.yml* using the following configuration. ``` disableCheckCSRF: contentTypeCheck: true tokenCheck: true ``` ## Unblocking users and password reset In case you need to reset a password for a user on startup, add the following to *config.yml.* The *new\_password* must comply with the configured password rules. The respective user will also be unblocked and enabled. ``` unblock: password: new_password username: existing_user ``` ## Cross-Origin resource sharing (CORS) allowlist This adds an allowlist for the 'Origin' HTTP header in requests where the HTTP request's 'URL' and 'Origin' do not match. It protects against [Cross-Site WebSocket Hijacking](https://christian-schneider.net/CrossSiteWebSocketHijacking.html) (CSWSH) attacks and should always be set. ``` grails: cors: allowedOrigins: - http://www.allowedorigin1.com - http://www.allowedorigin2.com ``` --- # Sharing Exports URL: https://docs.valsight.ai/sharing-exports/ Description: With the introduction of the Export Manager, it is now possible to provide access to exports for other projects in the same Valsight instance. In this way, t… With the introduction of the Export Manager, it is now possible to provide access to exports for other projects in the same Valsight instance. In this way, the target project(s) can directly access and import your exports as a data source, for example to duplicate your nodes and scenarios. > **Sharing exports is a licensed feature.** If it is not part of your licence, the ‘Share with other projects’ checkbox is greyed out with the note ‘This feature is not included in your license’. Ask your administrator whether it can be enabled for your instance. You can do this by checking the 'Share with other projects' box when [**creating an export**](/export-manager/). Alternatively, you can share an export after it has been created using the Export Manager. Open the export Settings using the three dots menu and navigate to the 'Edit Target Projects' tab. Activate the checkbox and select the desired projects you want to give access to this export. ![image-20240603-084720.png](./images/5549162508.png) > Sharing an export will automatically save the export indefinitely. Search and select one or multiple projects which you wish to share this and every future version of this export with. The project will then be granted access to view and import this export into their data sources. ## Importing shared exports To import an export from another project that has been shared, navigate to your project's Data sources. Create a new data source from the External Project tab and fill in the form for your desired export. * Select the source project from which to import data from * Select the export * Select the desired version of the export (the latest version will be imported if left blank) (see below, 'Versioning) * Select the tables to import, aka the nodes. Leave blank to import the entire export * Choose the exports name as the name for the data source or assign a custom name. * To restrict access to this data source, assign it to a specific model in your project. Note that you will need to ensure that the dimensions are the same between projects so that you can use the export in the target project without any problems. ![image-20240603-085109.png](./images/5548933151.png) ## Versioning Giving access to an export allows you to update it if you make any changes. The target project will be able to update the export to the latest version. You can create a new version after making changes to the model or scenario in the export manager. Open the three-dot menu of the export and click “Create new Version”. If you only want to share one version, it is recommended that you create a separate export for it. ## Updating the data source To update a data source to a newer version, go back to Data Sources and click on the required data source. Navigate to the 'Version' dropdown and select the newer version. ![image-20240603-085532.png](./images/5549719555.png) Click on ‘Re-import tables’ and confirm again to import and override the data source with its newer version. ![image-20240603-085551.png](./images/5548834856.png) Note: Updating a table will overwrite all previous data and may cause errors in nodes or scenarios. This step is reversible if the old version of the export still exists. Simply navigate back to the data source and re-import the previous version of this export. ## Related * [Export Manager](/export-manager/) --- # Sharing Scenarios URL: https://docs.valsight.ai/sharing-scenarios/ Description: When you share a Scenario, a snapshot of it is created that includes all of its current Assumptions and their data. This will become available to all users. When you share a Scenario, a snapshot of it is created that includes all of its current Assumptions and their data. **This will become available to all users.** Subsequent changes to the original Scenario will **not automatically refresh** the shared Scenario, so you have to **share it again** if you want to update the shared version and make these new changes available to other users. Sharing a scenario that has **Line-Item Variants active**, will only include the active Variants. ## Sharing scenarios To share a Scenario, open a Simulation Workspace and navigate to the first tab in the Workspace. You should see the Scenario Manager with your existing Scenarios and Assumptions. If you click on the button next to the Scenario you want to share, you will see the Context menu for the Scenario. Click on the entry "share" to open the "share Scenario" dialog. ![image-20240206-084244.png](./images/5368348678.png) A shared Scenario is created with the original name and a version to help you keep track of changes. You will see the generated name of the shared Scenario in the dialog. You can also add comments to the shared version here that will be visible to other users. ![image-20240206-084402.png](./images/5368807449.png) ## Building scenarios based on other scenarios Scenarios can logically reference other Scenarios by a) being based on another workspace scenario or model scenario or by b) including another Scenario for Simulations as an Assumption. In both cases, the technical relationship is the same, meaning that all assumptions that are in A are also active in B. You can configure the base of a scenario when you create or edit the scenario in the Scenario Manager using a combobox. This combobox should list all your created scenarios and the scenarios that have been shared with you. By default, the scenario of the workspace is selected. You can configure 'chains' of scenarios building on top of each other. A chain always has to end with a scenario that is based on a model scenario. ![image-20240206-084838.png](./images/5368905732.png)![image-20240206-085024.png](./images/5368840201.png) ## Using a shared scenario as assumption You can add a shared scenario as an assumption to your Scenario Manager with the "+ assumption" button in the upper right corner of the Scenario Manager. The arrow on the right side inside the button will open the dropdown menu. ![image-20240206-085348.png](./images/5368578070.png) When you click on the menu entry for scenario assumptions, you are presented with a list of scenarios that you have shared or that have been shared for you. Note, that those scenarios that you have already added as scenario assumptions will not show in the dialog. ![image-20240206-085912.png](./images/5368643602.png) Select the scenarios that you want to add as assumptions and and click on the "Add" button. The scenario assumptions will show up as rows in the Scenario Manager and you can activate them in your other scenarios to use the assumptions that are active in the scenario associated with the scenario assumption. ![image-20240206-085817.png](./images/5368774668.png) ## Manage shared scenarios You can unshare any scenario you have shared if it is not currently used and view all scenarios that have been shared with you. To manage the scenarios that have been shared with you and that you have shared, go to the list of workspaces. In the upper right corner, a "Manage Scenarios" button is available next to the "Add" button. Click on the "Manage Scenarios" button to open the shared Scenario Manager. ![image-20240206-090045.png](./images/5368938514.png) The manager dialog displays all the scenarios that you have shared by default. To see the scenarios others have shared with you, use the "Show all shared versions" link at the bottom. Select the scenarios you want to unshare and click the "Unshare" button to confirm your selection. The "Used by" column has detailed information which workspace and which scenario is currently using your shared scenario. Whether a shared scenario can be unshared depends on the scenario and on your own user: * **The scenario must not be in use.** A scenario that is still used in any workspace cannot be unshared, whoever you are. * **You can unshare the scenarios you shared yourself.** * **Project admins and global admins can unshare any scenario**, including ones other users shared. * **Analyst users cannot unshare at all**, not even a scenario they shared themselves. The selection also has to stay inside one project. Selecting shared scenarios from two different projects rejects the whole request with "Cannot unshare from multiple projects at the same time." ## Deleting all shared scenarios (admin only) In some cases, such as after duplicating a project, it may be beneficial to delete all shared scenarios in a project. To do this, admins can navigate to the Valsight Settings page, click on 'Projects' and navigate to the desired project with the shared scenarios. To delete all shared scenarios, click on the 'Delete all shared scenarios' button next to the 'Delete' button. > **This purges the whole project's version history, not only its shared scenarios** > > Despite the button's name, the action is a project-wide versioning purge. It removes every saved version of every assumption and scenario in the project, including versions in workspaces that were never shared, and it resets the version counters of the workspaces that remain. The confirmation dialog lists what it does: > > * Delete all versions of assumptions and scenarios in workspaces > * Delete all shared scenarios and scenario assumptions in workspaces > * Remove scenario data from workflow submissions > * Remove parent scenarios from scenarios > * Reset workspace default scenarios > > This is an Admin only function and is irreversible. Two things to know before you run it: * **The project must not be locked.** On a locked project the action is refused with "The project is locked. Unlock it to make changes." and nothing is deleted. Unlock the project first, and consider locking it again afterwards. * **Workflow history loses its scenario links.** Workflow submissions and timeline entries that referenced a shared scenario keep their entries, but the reference to the scenario is cleared. The purge is written to the security audit log. Please ensure that you are aware of all shared scenarios by checking the 'Manage Shared Scenarios' overview as shown above. ![Group 47.png](./images/5849284627.png) --- # SHIFT URL: https://docs.valsight.ai/shift/ Description: The SHIFT function shifts the input node by a given offset amount on a specified level. The shift amount can be a constant number or a node that provides different offsets per entry. **Category:** [Compare periods](/compare-periods/) ## Overview The **SHIFT** function **shifts the input node by a given offset amount on a specified level.** The shift amount can be a constant number or a node that provides different offsets per entry. Use this function when you need a custom offset on a specific level instead of a fixed previous-period helper or a rolling aggregation. ## Syntax `SHIFT('Node', "LevelName", ShiftAmount)` `SHIFT('Node', "LevelName", 'ShiftNode')` **Example usage:** `SHIFT('Revenue', "Year", 1)` ## Parameters | Parameter | Description | Type | Required | | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------ | -------- | | **Node** | Input node that is shifted, specified in single quotes (e.g.`'Profit'`) | Node reference | Yes | | **Level** | The level along which data is shifted, specified in double quotes (e.g.`"Year"`). The input node must have data on this level. | Level name | Yes | | **ShiftAmount** / **ShiftNode** | The offset to shift by. Can be a constant number or a node reference. | Number or Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------ | | Dimensionality | Preserved (same levels as input) | | Values | Repositioned along the specified level by the offset amount | | Row count | May decrease if shifted values fall outside the level bounds | ## Watch out * A **positive** shift amount moves values to earlier periods. A **negative** value moves them to later periods. This is the opposite of what many users expect. * For non-time dimensions, shifting is only allowed on the **lowest level** in the hierarchy. * Shifting on linked (extended) levels is not supported. * When using a node as the shift amount, its levels must match the input node's levels. * A **constant** offset with decimal places is cut back to a whole number, so `1.7` shifts by 1. * A **node** used as the offset must contain whole numbers only. A single value with decimal places makes the calculation fail with an error rather than being rounded. ## Examples ### Shift on the year dimension (positive vs. negative) This example illustrates how the sign of the ShiftAmount controls direction. **Input node:** `'Revenue'` | Year | Revenue | | ---- | ------- | | 2025 | 100 | | 2026 | 120 | | 2027 | 140 | **Formula:** `SHIFT('Revenue', "Year", 1)` *(positive → shifts data backwards)* | Year | SHIFT Result | | ---- | ------------ | | 2024 | 100 | | 2025 | 120 | | 2026 | 140 | The 2025 value now appears in 2024. Each value has moved one year into the **past**. **Formula:** `SHIFT('Revenue', "Year", -1)` *(negative → shifts data forward)* | Year | SHIFT Result | | ---- | ------------ | | 2026 | 100 | | 2027 | 120 | | 2028 | 140 | The 2025 value now appears in 2026. Each value has moved one year into the **future**. ### Shift by a constant amount This example shifts all values on the `Contract Age` level by the same constant offset. **Input node:** `'Contracts'` | Contract Age | Contracts | | ------------ | --------- | | 1 | 10 | | 2 | 20 | | 3 | 30 | **Formula:** `SHIFT('Contracts', "Contract Age", -1)` | Contract Age | SHIFT Result | | ------------ | ------------ | | 1 | | | 2 | 10 | | 3 | 20 | | 4 | 30 | ### Shift by values from another node This example uses a second node to define different shift amounts for each contract type. **Input node:** `'Contracts'` | Contract Age | Contract Type | Contracts | | ------------ | ------------- | --------- | | 1 | A | 10 | | 2 | B | 20 | | 3 | C | 30 | **Input node:** `'Shift Node'` | Contract Type | Amount | | ------------- | ------ | | A | -1 | | B | -2 | | C | -3 | **Formula:** `SHIFT('Contracts', "Contract Age", 'Shift Node')` | Contract Age | Contract Type | SHIFT Result | | ------------ | ------------- | ------------ | | 2 | A | 10 | | 4 | B | 20 | | 6 | C | 30 | ### Shift by offsets defined per level value This example uses a shift node on the same level that is being shifted, so each contract age gets its own offset value. **Input node:** `'Contracts'` | Contract Age | Contract Type | Contracts | | ------------ | ------------- | --------- | | 1 | A | 10 | | 2 | B | 20 | | 3 | C | 30 | **Input node:** `'Shift Node'` | Contract Age | Amount | | ------------ | ------ | | 1 | 1 | | 2 | 1 | | 3 | 1 | **Formula:** `SHIFT('Contracts', "Contract Age", 'Shift Node')` | Contract Age | Contract Type | SHIFT Result | | ------------ | ------------- | ------------ | | 0 | A | 10 | | 1 | B | 20 | | 2 | C | 30 | ## Related | Function | When to use instead | | ------------------------ | ----------------------------------------------------------------------------------------------------------------- | | [PY](/py/) | When you need a fixed one-year shift for year-over-year comparisons without a custom offset. | | [TIMELAG](/timelag/) | When an effect should appear gradually or with a delay across time periods. | | [MOVINGSUM](/movingsum/) | When you want to aggregate values over a rolling window instead of moving them to different positions on a level. | --- # Shifting Assumptions URL: https://docs.valsight.ai/shifting-assumptions/ Description: Simulate the effect of revenue & cost streams as well as cash inflows & outflows delay or advancement through shifting an Assumption or its part. The shift d… Simulate the effect of revenue & cost streams as well as cash inflows & outflows **delay or advancement** through shifting an **Assumption** or its part. The shift duration is always declared at monthly basis. Positive values represent delays and negative advancements. If the data is defined on yearly basis, the shift moves a portion of the values across the years (e.g. 6 month shift of yearly revenue will move 50% of year x to year x+1 and so on). > Shifting is not available everywhere. It is blocked outright on projects that use the week time dimension, where the Shift button stays disabled behind ‘Shifting is not allowed with projects that use weeks.’, and assumption groups that live in a shared workspace cannot be shifted at all. ![shifting assumption eng v2.18.png](./images/5094190884.png) The dialog offers two mutually exclusive options, not two tickboxes: * **Overwrite line-items** shifts the existing line-items in place. The assumption is then flagged so that the next version you save has to be a new one. * **Create new assumption** duplicates the assumption with the shift applied. The copy is named *‹name› (Delayed)* unless you type a name of your own, and it contains **all** line-items of the assumption, not only the ones you ticked. Picking *Create new assumption* reveals a name field and the checkbox **Activate in all scenarios**, which activates the new versions everywhere the original was active and deactivates the original. ## How to shift assumptions inside the Scenario Manager Open the Scenario Manager and select the *three dots* next to the Assumption you want to Shift. The option to *Shift* the Assumption will appear as shown in the picture below. ![image2023-5-31\_11-53-3.png](./images/5148409897.png) A line-item can only be shifted if all four of these hold; the rest cannot be selected in the dialog: * it enters data absolutely (`+`), not as a relative percentage * it has a time level * that time level is no finer than Month, so Year, Quarter and Month qualify and Day does not * source and destination line-items sit on the same node Only line-items are shiftable. A shared scenario added to the assumption is silently not offered. --- # SIGNUM URL: https://docs.valsight.ai/signum/ Description: Extracts the sign of a number. Positive numbers become 1, negative numbers become -1, and zero remains 0. Use when you need to reduce a value to its sign for directional logic, classification, or further numeric transformations. **Category:** [Math & numeric](/math-numeric/) ## Overview The **SIGNUM** function **extracts the sign of a number**. Positive numbers become 1, negative numbers become -1, and zero remains 0. Use this function when you need to reduce a value to its sign for directional logic, classification, or further numeric transformations. ## Syntax `SIGNUM('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | ## Examples ### Extracting the sign of positive, negative, and zero values This example shows how SIGNUM returns `-1` for negative values, `0` for zero, and `1` for positive values across products and years. **Input node:** `'A'` | Year | Product | Value | | ---- | ------- | ----------- | | 2025 | Car | -1 | | 2025 | Truck | 3 | | 2026 | Car | 0 | | 2026 | Truck | -8561451155 | | 2029 | Car | 65452141023 | **Formula:** `SIGNUM('A')` | Year | Product | SIGNUM Result | | ---- | ------- | ------------- | | 2025 | Car | -1 | | 2025 | Truck | 1 | | 2026 | Car | 0 | | 2026 | Truck | -1 | | 2029 | Car | 1 | ## Related | Function | When to use instead | | ---------------- | -------------------------------------------------------------------------------------------------------------------- | | [ABS](/abs/) | When you need the absolute value of each number instead of only its sign. | | [ROUND](/round/) | When you need to round numeric values for presentation or calculation steps instead of reducing them to -1, 0, or 1. | --- # Simulations & Analysis URL: https://docs.valsight.ai/simulations-analysis/ Description: Simulations in Valsight build scenarios on top of a data baseline by applying line items to simulatable nodes, and analysis compares and interprets those sce… **Simulations** in Valsight build scenarios on top of a data baseline by applying line items to simulatable nodes, and **analysis** compares and interprets those scenarios using charts, bridges, and tables. ![image-20260521-150442.png](./images/7008813079.png) --- # Single-Sign-On (SSO) Configuration URL: https://docs.valsight.ai/single-sign-on-sso-configuration/ Description: Valsight Supports SAML2.0 and Open ID Connect for Authentication with your IdP. Valsight Supports SAML2.0 and Open ID Connect for Authentication with your IdP. For ease-of-operation our recommendation is to use Open ID Connect, if possible. > SSO configuration is a paid add-on for the Teams edition, and is included in the Corporate > and Enterprise editions. Which page applies depends on how your Valsight runs: | If your Valsight is | Go to | | ------------------- | --------------------------------------------------------------------------------------------------------------------------- | | A cloud instance | [Cloud SSO with Valsight ID](/cloud-openid-connect/) — your IdP connects to Valsight ID, and you register one redirect URL. | | On your own servers | [OpenID Connect](/openid-connect/) under On-Premise Installation, where the configuration lives on your instance. | [Entra / AAD Configuration](/entra-aad-configuration/) covers the Entra-specific details of the direct-to-instance setup, in which Entra talks to your instance rather than to Valsight ID. --- # Sliders URL: https://docs.valsight.ai/sliders/ Description: Put the sliders for chosen line-items on the worksheet, so simulations can be run without opening the Scenario Manager. A slider tile puts the sliders for chosen line-items directly on a worksheet, so a reader can adjust values and see the effect without opening the Scenario Manager. ## What it is You choose which line-items a tile shows. That can be one slider on its own, or all the sliders relevant to a sheet gathered into a single tile. ![A slider tile holding one slider per line-item](./images/6987808779.png) Add one by adding a chart to your workspace and selecting **Slider** in the chart type selection. ## When to use it * You want a focused simulation on the sheet itself, with only the handful of line-items that matter there. * You are presenting and want to adjust an assumption without leaving the sheet. * You want a reader who does not know the model to still be able to try a change safely. Use a **[split slider](/split-sliders/)** instead when the total has to stay fixed and you only want to shift shares between its parts. ## Configuration Everything is reached from the tile itself: | Control | What it does | | ----------------------- | -------------------------------------------------------------------------------------------------- | | **Edit** button | Change which line-items the tile shows sliders for. | | **Settings** | Rename, move, duplicate or delete the tile. | | **Before/after column** | Show the impact of the slider's value next to it. | | **Reset** | Reset a single slider from the button to its right, or every slider in the tile from the settings. | ## Good to know * **A slider tile cannot leave its workspace.** It cannot be duplicated or moved to another workspace. * **Line-items with more than one variant are not supported.** A slider needs a single variant to act on. * **The line-item must resolve to a single row.** Any line-item still spread over several dimension values fails with ‘Cannot show sliders for line-items with more than a single row in the data view.’ Filter or reconfigure the line-item until one row is left. This is the more common of the two failures, because any dimensioned line-item hits it. * **Step size comes from the line-item, not the tile.** Minimum, maximum and step size are set in the **Slider** section of the line-item's **Details** tab in the [Scenario Manager](/sliders-in-the-scenario-manager/). ## Related * [Split Sliders](/split-sliders/): redistribute a total across its parts while the total stays fixed. * [Input Tables](/input-tables/): another way to simulate directly on a sheet, by typing values. * [Sliders in the Scenario Manager](/sliders-in-the-scenario-manager/): configuring sliders as part of the Scenario Manager. --- # Sliders in the Scenario Manager URL: https://docs.valsight.ai/sliders-in-the-scenario-manager/ Description: Sliders in the Scenario Manager allow you to modify existing line-items with the ease of a slider without having to enter the line-item data itself. Sliders in the Scenario Manager allow you to modify existing line-items with the ease of a slider without having to enter the line-item data itself. ## Preparation 1. Add a resizable Scenario Manager to a sheet with the charts you want to see get updated. Click on the dropdown next to the 'Chart' button and choose Scenario Manager. A resizable version of the Scenario Manager will appear. 2. Show the “Slider” column in the Scenario Manager. The Slider will appear. 3. Which Line-Items do you want to display Sliders for? Sliders are only displayed for **line-items with only one row**. Filter your line-items via ‘Details’ > ‘Manage filters and levels’ to one row. The slider should now appear. 4. Set the minimum, maximum, and the step size in the 'Details' of the line-item. E.g. a minimum of -100, a maximum of 100, and a step size of 25 will produce a slider like below. You will only be able to choose the values -100, -75, -50, -25, 0, 25, 50, 75, 100. ![image2020-6-18\_16-47-21.png](./images/5094192947.png) > **Line-item variants** > > Sliders cannot be used for Line-Items that have more than one Variant. > **The row count is the filtered row count** > > The one-row test is applied after the workspace's filters have been applied on top of the line-item's own filters. A line-item with several rows of its own can therefore become slider-eligible through the workspace filter, and a line-item that has a slider can lose it when the workspace filter changes. ## Working with sliders Now you can change the slider and see the effects in your charts. Changing the slider will change the data in the line-tiem so all your changes are saved like before. **How to use the Slider for Line-Items with multiple rows** If you want to have a slider that distributes a value over multiple years (e.g. total turnover for 2020-2023) or copies a value to multiple years (e.g. inflation % for 2020-2023), then you have to build that logic in the model. Build the Node in such a way that it takes only one value as input and the following node can then distribute or copy it over a dimension. ## Resetting sliders If you want to reset all Sliders, click on the three-dot menu in the change column or the three dot menu on the slider tile itself. ![reset sliders.png](./images/5094194638.png) ## Related * [Sliders](/sliders/): can also be displayed as a chart directly on the dashboard * [Input Tables](/input-tables/): another possibility to simulate live on the dashboard --- # Sort Key Settings in Nodes URL: https://docs.valsight.ai/sort-key-settings-in-nodes/ Description: Set a sort key on a node to control the order nodes appear in within a model tree. A node in a [model tree](/model-tree/) that has no sort key sorts under its own name, which is why costs land above revenue. That order rarely matches how a statement is read. A node's **sort key** fixes it. ## Goal Put the nodes of a model tree in a deliberate order, so the tree reads the way your audience expects. ## Prerequisites * Edit rights on the model the nodes live in, since the setting is on the node rather than on the chart. ## Steps 1. Open the model and select the node you want to move. 2. Click **Show Advanced Settings**. 3. Enter a **sort key**. The keys sort in ascending order, so give the node that should come first the lowest key. A node left without a key sorts under its own name, alongside the nodes that do have keys. The comparison is numeric-aware, so `A2` comes before `A10` rather than after it. Sorting is applied among siblings, that is among the nodes that share a parent, not across the tree as a whole. In this example **Revenue** is given `A1` and **Costs** is given `B2`, which puts revenue above costs: ![The sort key field under a node's advanced settings, set to A1 on the Revenue node](./images/5094193207.png) 4. Repeat for the other nodes you want to place. ## Verify The model tree is sorted accordingly, with revenue above costs: ![The model tree with revenue sorted above costs](./images/5094193204.png) If nothing moved, check that you set the key on the node rather than in the chart, that the keys you used actually sort in the intended order, and that the nodes you are trying to reorder share a parent. ## Related * [Model Tree](/model-tree/): the chart type this order applies to. * [Advanced Node Settings](/advanced-node-settings/): the other settings on a node, including hide in workspace. * [Sorting Level Values](/sorting-level-values/): ordering the values within a single chart, rather than the nodes across a model. --- # Sorting Level Values URL: https://docs.valsight.ai/sorting-level-values/ Description: Put the level values of a chart or table in a custom order, per level and per chart. The level values of a chart or table are the rows of a table and the entries along the x axis of a chart. They can be put in any order you want, one chart at a time. ## What it is By default level values follow the order they have in the model. Sorting is set per level, so a chart with **Country** and **City** has its own order for each of them, and it applies to that chart only. ## When to use it * The default order does not match how your audience reads the figures, for example when a scenario should come last. * Rows need to follow the structure of a statement rather than the structure of the model. * Labels are disappearing where they collide, and the order decides which one wins. To change the order nodes appear in within a model tree rather than in one chart, set their sort keys instead: see [Sort Key Settings in Nodes](/sort-key-settings-in-nodes/). ## Configuration 1. Select the chart or table. The chart editor opens on the right. 2. In the **Axes** section, click the sort button next to the level you want to reorder. The levels are grouped under headings named after the chart: **Rows** and **Columns** for a table, **X-Axis** and **Data Series** for most charts. 3. Choose a sort mode: | Mode | What it does | | ----------------------------- | ------------------------------------------------------- | | **Alphabetical - ascending** | Orders the level values by name, A to Z. | | **Alphabetical - descending** | Orders them by name, Z to A. | | **Manual** | Lets you drag the level values into any order you want. | | **By value - ascending** | Orders them by a value you pick, smallest first. | | **By value - descending** | Orders them by that value, largest first. | 4. For either **By value** mode, pick the reference under **Value to sort by**. The list holds the values on the opposing axis. Leaving it empty is rejected with "You need to select a value for value based sort." 5. Confirm. ![The Axes section of the chart editor, with a sort button next to the row and column levels](./images/axes-section.png) ![The sort dialog, ordering level values by drag and drop](./images/5243633735.png) ## Good to know * **Sorting here sorts one chart.** The model is untouched, and other charts keep their own order. For a model-wide order, use [Sort Key Settings in Nodes](/sort-key-settings-in-nodes/). * **Sorting by value is not always offered.** Where it is unavailable the dialog shows the three other modes only. Values on time bridges cannot be sorted, and neither can values carrying the delta setting. * **Order decides which data label wins.** In area and line charts, where labels collide the higher-sorted node's label is the one shown. See [Overlapping Data Labels](/overlapping-data-labels/). * **Order and formatting are separate.** Subtotal and total formats sit in the styling dialog: see [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/). ## Related * [Sort Key Settings in Nodes](/sort-key-settings-in-nodes/): the order nodes have in a model tree. * [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/): colors, value labels and subtotal formats. --- # Split Sliders URL: https://docs.valsight.ai/split-sliders/ Description: A split slider redistributes a total across its parts on the worksheet, keeping the total fixed as you move the handles. A split slider redistributes a total across its parts, without changing the total. Drag one handle and the others move to compensate, which makes it the tile to reach for when you are adjusting a product mix, reallocating a budget or rebalancing resources. ## What it is A split slider shows one line-item as a single track with a handle between each pair of neighboring parts. The legend below the track names every part and its current share. ![A split slider named Substitution Quote, with one track split into three shares of 28, 28 and 44 per cent](./images/split-slider.png) The total is fixed. Moving a handle takes from one part and gives to another, so the shares always add up to the same figure they started at. This is the difference from an ordinary [slider](/sliders/), which changes one line-item's value on its own and lets the total move with it. Dragging one handle rebalances the others for you. When two shares sit close together and their handles overlap, click the empty track between them to push them apart. Each split slider shows one line-item at a time, in one of two views: | View | What you get | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Change View** | You enter the values directly, as changes. | | **Result View** | The values shown include the effects of every other line-item active in the chosen scenario. For your edits to reach that scenario, the selected variant must be **active** in it. | A scenario is selected in both views; what differs is only what the numbers mean. **Result View** is preselected for a split slider. ## When to use it * You want to shift the mix between products, regions or technologies while the volume stays where it is. * You want to move budget from one cost line to another without changing what you are spending overall. * You want people to rebalance an allocation on the worksheet itself, rather than in the Scenario Manager. Use another tile instead if the total is what you want to change: * A **[slider](/sliders/)** changes a single line-item by an absolute amount, and the total moves with it. * An **[input table](/input-tables/)** is the way to change the total that a split slider then divides up. * A **[line-item table](/line-items/)** is the better fit when the values should not be tied to a fixed total at all. ## Configuration 1. Add a chart to your worksheet and select **Split Slider** in the chart type selection. 2. Select the **line-item** you want to redistribute. 3. Choose a **variant**, if the line-item has more than one. 4. Select the **View**, either **Change View** or **Result View**. 5. Select the **scenario** you want to apply. **Create** stays disabled until the variant, the view and the scenario are all chosen. 6. Click **Create** to place the split slider on the worksheet. *Tip: open the Scenario Manager in a second tab and check the line-item's configuration before you create the tile, since the line-item decides both which parts appear and how large a step each handle moves in.* Once the tile is on the sheet, the chart editor lets you: | Setting | What it does | | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | **Line item**, **Variant**, **View**, **Scenario** | Point the tile at different data, or switch between Change View and Result View, without rebuilding it. | | **Sorting** | The **Levels** button opens the sort dialog, which reorders the parts and with them the legend. | | **Filters** | Cut a large line-item down to the parts you actually want to redistribute. | **Step size** is not a chart setting. It comes from the line-item itself, under **Sliders > Step Size** in the [Scenario Manager](/sliders-in-the-scenario-manager/). Set it to match the scale of your data: too large and you cannot fine-tune a share, too small and the handles feel unresponsive. ## Good to know * **Twenty parts is the limit.** Above 20 rows the tile reports that there are too many items to display instead of drawing the slider, which keeps the handles far enough apart to be usable. Filter the line-item down if you hit it. * **Negative values are not supported.** A line-item has to hold positive values only, because a mix of signs makes the total ambiguous to divide up. * **A line-item that is all zeros cannot be split.** The tile reports that there is nothing to split rather than showing empty handles. Pick a line-item that carries data. * **Handles can end up on top of each other.** When two shares are close, click the empty track between the handles to push them apart, rather than trying to grab one. * **A read-only tile means stale data.** A split slider locks itself when the data behind it is out of date, so that you cannot write changes onto figures that no longer hold. Reload the page to get editing back. * **An empty tile usually means the filters left nothing.** Check the tile's filters against the line-item's values. * **A split slider is not exported and not presented.** It is left out of XLSX exports, and in [presentation mode](/using-the-presentation-mode/) the tile shows a note instead of the slider. **Move or duplicate** does work, including to another workspace. ## Related * [Sliders](/sliders/): the ordinary slider tile, for changing one line-item on its own. * [Input Tables](/input-tables/): enter values on the worksheet, including the total a split slider divides. * [Sliders in the Scenario Manager](/sliders-in-the-scenario-manager/): where step size and the other slider settings live. * [Chart Types](/chart-types/): the other tiles you can place on a worksheet. --- # SQRT URL: https://docs.valsight.ai/sqrt/ Description: Returns the square root of each value in the input. Use when you need the square root of positive values for scaling, normalization, or mathematical transformations. **Category:** [Math & numeric](/math-numeric/) ## Overview The **SQRT** function **returns the square root of each value in the input**. Use this function when you need the square root of positive values for scaling, normalization, or mathematical transformations. ## Syntax `SQRT('Node')` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | ## Watch out * Use [POWER](/power/) for other roots (e.g. cube roots via a fractional exponent). * A **negative input value** makes the whole calculation fail, not just that one row. SQRT is a POWER with the exponent 0.5, and a negative base with a fractional exponent is undefined. Wrap the input in `MAX('Node', 0)` or [ABS](/abs/) if negatives are possible. ## Examples ### Square root of positive input values This example shows the square root computed for a node with simple positive values. Each result is the square root of the corresponding input value. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 4 | | 2026 | 9 | | 2027 | 25 | **Formula:** `SQRT('A')` | Year | SQRT Result | | ---- | ----------- | | 2025 | 2 | | 2026 | 3 | | 2027 | 5 | ## Related | Function | When to use instead | | ---------------- | -------------------------------------------------------------------------------------------------------- | | [POWER](/power/) | When you need other roots or a general exponentiation instead of only the square root of a single input. | | [LN](/ln/) | When you need a logarithmic transformation instead of taking the square root of the input. | --- # Stacking and Stack Totals URL: https://docs.valsight.ai/stacking-and-stack-totals/ Description: Stack the bars or areas of a chart so the data series add up to one total, and choose whether to label that total. Columns, bars and areas sit next to each other by default. Stacking places them on top of each other instead, so the height of a bar is the total and each segment is one part of it. ## What it is Switch on the **Stacked** checkbox next to the chart type buttons in the chart editor. Use it when the data series all belong to the same total, for example the parts of a gross profit effect. The checkbox is offered on column, bar, area, line and mixed charts. Tables, pie charts, packed bubble charts and waterfall charts do not have it. ![Stacked column chart of the gross profit effect per engine type, with the positive and negative sums labeled above and below each bar](./images/stacked-column-chart.png) Stacking applies to a whole chart type. To stack most data series but keep one of them separate, for example a benchmark line drawn across the stack, use a [mixed chart](/mixed-charts/) instead. ## When to use it * The data series are parts of one figure and their sum is meaningful. * You want to show both a total and its composition without a second chart. * Values run both above and below zero and you want the positive and negative parts read separately. Leave stacking off when the data series are alternatives rather than parts, for example the same key figure in different scenarios. Those belong side by side. ## Configuration Once a chart is stacked, you can label the total of each bar. The **Stack Totals** drop-down in the chart editor offers three options. ![The Stack Totals drop-down in the chart editor, open with its three options](./images/stack-totals-dropdown.png) | Option | What you get | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | **None** | The default for a new chart. Only the proportional values of the segments within a bar are shown, with no total. | | **Combined sum** | The total value of the whole bar is shown on top of it. | | **Positive/negative sums** | The sum of the negative values is shown at the bottom end of the bar and the sum of the positive values at the top end. | ### None ![A stacked column chart showing only the segment values, with no total](./images/5094208738.png) ### Combined sum ![The same chart with one combined total labeled above each bar](./images/5094208726.png) ### Positive/negative sums ![The same chart with the negative sum labeled below each bar and the positive sum above it](./images/5094208743.png) ## Good to know * **Setting several data series to bars does not stack them.** Stacking is the separate **Stacked** checkbox, and without it the bars stand side by side. * **No Stack Totals drop-down?** It only appears once **Stacked** is on, and never on pie or waterfall charts. * **A mixed-chart series set to Line never stacks.** It runs in front of the stack whether **Stacked** is on or off. This exemption is specific to the **Line** option in a [mixed chart](/mixed-charts/): on a plain line chart the lines do stack when **Stacked** is on, and a mixed-chart series set to **Spline** stacks with the other splines. * **Stack Totals can rescue overlapping labels.** When data labels collide, a combined sum often reads better than the individual values. See [Overlapping Data Labels](/overlapping-data-labels/). ## Related * [Mixed Charts](/mixed-charts/): show one data series differently from the rest, so it stays out of the stack. * [Formatting Charts](/chart-configuration/): sorting, colors, scales and table styles. --- # STRETCH_CURVE URL: https://docs.valsight.ai/stretch-curve/ Description: Stretches the curve or curves defined in the curves input over the X axis by a factor defined in the stretch input. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **STRETCH\_CURVE** function **stretches the curve or curves defined in the curves input over the X axis by a factor** defined in the stretch input. You can specify the X coordinate where the stretching begins with the optional start input. The stretching begins at 0 by default. `start` is a cut-off, not a fixed anchor: points before it keep their X coordinate unchanged, and points **from `start` onwards**, including the point at `start` itself, have their X coordinate multiplied by the stretch factor. In the example below project B starts at X = 2 with a factor of 2, so the point at X = 2 moves to X = 4 and the curve is shifted as well as stretched. The X coordinates are represented by the `Sequence` level in the curves input, and the Y coordinates are represented by the values of the curves input. Use this function when you want to stretch or compress an existing profile along the time axis instead of only delaying it. ## Syntax `STRETCH_CURVE('CurvesNode', 'StretchNode' [, 'StartNode'])` ## Parameters | Parameter | Description | Type | Required | Default | | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- | ------- | | **CurvesNode** | Definition of curves as a set of `(X, Y)` points in the coordinate system. X values are taken from the `Sequence` level and Y values from the node values. This input must contain the `Sequence` level. | Node reference | Yes | -- | | **StretchNode** | Stretch factor. It must not contain the `Sequence` level and may only contain levels that are also present in `CurvesNode`. It can also be a constant. | Node reference or number | Yes | -- | | **StartNode** | X coordinate where stretching begins. It must not contain the `Sequence` level and may only contain levels that are also present in `CurvesNode`. It can also be a constant. | Node reference or number | No | `0` | ## Examples ### Stretching project-specific curves with an optional start point This example shows two input curves, one for project A and one for project B. Each project uses its own stretch factor, and only project B receives an explicit start point; project A therefore defaults to `0`. **Input node:** `'CurvesNode'` | Project | Sequence | Value | | ------- | -------- | ----- | | A | 0 | 0 | | A | 1 | 1 | | A | 2 | 1 | | A | 3 | 2 | | B | 0 | 0 | | B | 1 | 1 | | B | 2 | 2 | **Input node:** `'StretchNode'` | Project | Value | | ------- | ----- | | A | 1.5 | | B | 2 | **Input node:** `'StartNode'` | Project | Value | | ------- | ----- | | B | 2 | **Formula:** `STRETCH_CURVE('CurvesNode', 'StretchNode', 'StartNode')` | Project | Sequence | STRETCH\_CURVE Result | | ------- | -------- | --------------------- | | A | 0 | 0 | | A | 1 | 0.67 | | A | 2 | 1 | | A | 3 | 1 | | A | 4 | 1.67 | | A | 5 | 2 | | B | 0 | 0 | | B | 1 | 1 | | B | 2 | 1.33 | | B | 3 | 1.67 | | B | 4 | 2 | ## Related | Function | When to use instead | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | [TIMELAG](/timelag/) | When you want a delayed effect at a chosen time granularity instead of stretching or compressing an existing profile. | | [SCHEDULEPROJECTS](/scheduleprojects/) | When you want to place project blueprints onto actual start periods instead of reshaping an already defined profile along the sequence axis. | --- # Structure Driver Models URL: https://docs.valsight.ai/structure-driver-models/ Description: This guide shows you how to structure a Valsight model so that it stays understandable, scalable, and easy to maintain as it grows. By the end, your model wi… Structure a Valsight model so that it stays understandable, scalable, and easy to maintain as it grows. By the end, your model will follow a clear flow from raw data to high-level KPIs, using submodels to separate concerns. ## Visual layout Driver models are structured from right to left, meaning that submodels and nodes should start at the right of the canvas and end on the left. Raw data and inputs appear on the right; final KPIs appear on the left. ## Core principles * **Define your target outputs first** Identify a small set of key metrics and KPIs you ultimately want to analyze, such as `'Revenue'`, `'EBIT'`, `'Headcount'`, `'Capacity Utilization'`. These outputs define the “head” of your model and should be placed on the left side of your canvas. * **Work backwards to inputs and drivers** For each KPI, determine which intermediate calculations are required and which input data or assumptions are needed to calculate them. This backward approach prevents unnecessary logic and unused data. * **Keep each node focused and interpretable** Design nodes so that each one answers a single, clear question. For example, calculate `'Unit Price'` and `'Units Sold'` separately, then derive `'Revenue'` from them. Avoid combining multiple steps into one complex node. * **Define and apply dimensions consistently** Decide early which dimensions are global across the model (for example, "`Time`", "`Region`", "`Product`", "`Business Unit`"). Apply them consistently and avoid adding niche dimensions that only apply to isolated nodes. * **Separate layers using submodels** Organize the model into submodels that reflect a logical flow from data to KPIs. Use numeric prefixes and descriptive names to make the order and purpose explicit. ## Recommended submodel structure ![Valsight\_Fish.PNG](./images/6699679753.png) Name submodels with numeric prefixes and clear purposes. The submodel structure can be visualized by clicking **Model Graph** in the upper right corner of the Model overview. | Prefix | Name | Purpose | | ------ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 500\_ | Data (Tail) | Raw inputs and source mappings. Nodes connect to data sources or perform basic cleaning and mapping. | | 400\_ | Drivers | Common assumptions like growth rates, FX rates, inflation, or standard cost rates for consistent reuse across the model. | | 3XX\_ | Operational Detail | Separate submodels for major operational areas (sales volumes, pricing, production capacity, costs, headcount). These calculate operational metrics that feed financial results. | | 2XX\_ | Financial Calculations | Financial statements and calculations (P\&L, cash flow, balance sheet). Aggregates operational outputs into financial results. | | 000\_ | KPIs (Head) | High-level KPIs and ratios. Reduce dimensions where appropriate to focus on management-relevant views (e.g., Time and Region only). | ## Notes * **Respect the flow direction** Ensure dependencies only point forward (right to left on the canvas). Nodes in earlier submodels (for example, `'Sales'` or`'P&L'`) should be available to later ones (like `'KPIs'`), not the other way around. * **Use submodels for access control** If different users should only see parts of the model, restrict access at the submodel level. This allows, for example, OPEX owners to work in cost submodels without exposure to the full model. ## What you have done Your model is now structured in clear layers, from data input on the right to detailed calculations, financial consolidation, and KPIs on the left. This structure improves readability, reduces complexity, and makes collaboration and scaling significantly easier. ## Related * [Submodels](/models/): add new submodels to your model --- # Styling Data Series, Columns and Rows URL: https://docs.valsight.ai/styling-data-series-columns-and-rows/ Description: Style a chart's data series or a table's columns and rows, from color and value labels to subtotal and total formats. Everything a chart or table is built from can be styled on its own: its color, the look of its value labels, whether a row reads as a subtotal, and whether it appears at all. ## What it is The chart editor puts these settings in one dialog, opened from the **Formatting** section. The two buttons there, and the title of the dialog, are named after whatever the chart is built from, so they change with the chart type: | Chart | Buttons you get | | --------------------------------- | ------------------------------ | | Table | **Columns** and **Rows** | | Column chart with **Stacked** off | **Groups** and **X-Axis** | | Column chart with **Stacked** on | **Stacks** and **X-Axis** | | Line, area, bar and the rest | **Data Series** and **X-Axis** | Whichever pair you get, both work the same way: a list on the left, and the properties of whatever you tick on the right. Styling is per entry, not per chart, so ticking two entries and changing a property applies it to both. That is how you color a whole group consistently without repeating yourself. ![The Formatting section of the chart editor, with the buttons that open the styling dialog](./images/5865865286.png) ## When to use it * You want a scenario, product or region to keep the same color across every chart on a sheet. * You want to highlight one data series and mute the others. * Value labels are colliding and you want to hide some of them. * You are building a profit and loss or cash flow statement and need subtotal and total rows to stand out. ## Configuration 1. Select the chart or table. The chart editor opens on the right. 2. Scroll to the **Formatting** section and click either of the two buttons named in the table above. 3. Tick one or more entries in the list on the left. Changes apply to everything ticked. 4. Set the properties described below, then click **Confirm**. ### Data series and columns | Property | What it does | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Color** | Sets the color of the data series itself, for example its line or its bars. | | **Show as** | Switches the data series between **Line**, **Bar**, **Area** and **Spline**. Mixed charts only, and only on the data series side, never on the x-axis. See [Mixed Charts](/mixed-charts/). | | **Font color** | Sets the color of the text shown on the data series. | | **Background color** | Sets a background color behind that text. | | **Format** | Applies **Bold**, *Italic*, underline, or regular, which is the default. | | **Orientation** | Rotates the value labels: vertical, horizontal or diagonal. | | **Value overlapping** | Allows the value labels of this data series to overlap instead of being dropped when space runs out. | | **Show values** | Shows the value labels on the data series. Clear it to hide them. | | **Hide** | Hides the whole data series from the chart, not only its labels. | ![The Data Series tab with one of three data series ticked and its properties on the right](./images/data-series-dialog.png) ### Rows Rows carry formats rather than colors, which is what makes a financial statement read like one. | Property | What it does | | --------------- | ------------------------------------------------------------ | | **Standard** | The row as normal text. This is the default. | | **Subtotal** | Bold, with a horizontal line above it. | | **Total** | Bold, with horizontal lines above and below it. | | **Indentation** | Moves the row to the right. Several steps deep are possible. | | **Hide** | Leaves the row out of the table. | ![The Rows tab with the formatting options for the selected row](./images/style-columns-and-rows.png) ### Deviations Both tabs carry a **Styling** group that only affects delta and comparison columns. | Property | What it does | | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | **Invert colors and numbers for deviations** | Swaps the up and down color and the sign, so a cost saving can read as green rather than as a negative. | | **Show negative numbers in parenthesis for deviations** | Wraps a negative delta in parentheses instead of giving it a minus sign. | ### Comparisons A fourth group, **Comparisons**, appears when every entry you have ticked is a comparison. | Property | What it does | | ---------------------------------- | ------------------------------------------------------------------------- | | **Hide comparison bars in tables** | Suppresses the in-cell bars a comparison column draws behind its numbers. | ## Good to know * **Some selections offer nothing to format.** A value with an active delta setting cannot be formatted, and the dialog says so instead of showing properties. Assumptions, assumption line-items and assumption properties can be neither sorted nor formatted, so selecting one leaves the dialog empty. Neither is a fault. * **Colors are per data series, not per node.** To set a color once for a whole model, see [Editing the Color Palette](/editing-the-color-palette/). * **Hiding a value is not the same as hiding a data series.** **Show values** controls the label, **Hide** removes the line or bar. * **Hiding a data series affects exports.** A series hidden through the **Hide** checkbox is excluded from a Formatted XLSX export but still present in a Raw XLSX or OData export. * **Show values needs numbers switched on for the whole chart.** If **Show numbers** is off in the **Formatting** section, the per-entry **Show values** option is disabled. * **Formats are per row, not per level.** Marking one row as a total does not mark its siblings. * **Order is set elsewhere.** This dialog styles entries but does not reorder them: see [Sorting Level Values](/sorting-level-values/). * **In a mixed chart, styling and chart type live in the same place.** The **Show as** option that turns a data series into a line, bar, area or spline sits alongside these properties. See [Mixed Charts](/mixed-charts/). ## Related * [Mixed Charts](/mixed-charts/): choose a different shape per data series. * [Sorting Level Values](/sorting-level-values/): the order the entries appear in. * [Table Formatting](/table-formatting/): table style, column widths and merged header cells. --- # Submission Details & Activity URL: https://docs.valsight.ai/submission-details-and-activity/ Description: The submission details page, where you promote, demote and re-share a Workflow submission and read the history of everything that has happened to it Every Scenario in a Workflow step has a submission behind it, and each submission has a page of its own. It shows where the submission stands, lets you promote or demote it, and keeps the full history: who moved it, when the Scenario was re-shared, which step imported it, and every comment anyone left. ## Opening a submission 1. Open the project and click the **Workflows** icon in the navigation bar on the left. Everyone with read access to the project has it. 2. Click the Workflow you want. Its submissions page opens. 3. The table has one row per Workflow step and one column per Scenario. Each cell is a single submission, showing its name, its status and, if you have the rights, buttons to promote or demote it on the spot. 4. Click the submission **name**. The status tag beside it is not a link. The page that opens has **Details** at the top and **Activity** underneath it. > **A Workflow still in ‘Draft’ has no submissions yet.** Clicking it opens its step configuration instead. Submissions are created when the Workflow is started. Contributors have a shortcut. In both the ‘Import Previous Steps’ and ‘Share Workflow Steps’ dialogues in the Scenario Manager, the step in the first column is a link to that step's submission, so you can read the history behind a set of numbers without leaving your work. ## The Details section Details holds the submission's current status, the description of the Workflow step it belongs to, and a link to the workspace it was made from. The description is set on the step rather than the submission, so every submission of that step shows the same text, and it reads ‘No description’ if the step was created without one. If you have no access to the workspace, that field says so instead of linking, but the rest of the page still loads, so you can follow a step that is not yours. ## Promoting, demoting and updating Three buttons sit in the page header, each greyed out when it does not apply to you or to the submission's current status. * **Promote** moves the submission on to the next status. It is unavailable once the submission is at the final status. * **Demote** moves it back one status. It is unavailable at the first status, and only project admins can demote out of ‘Done’. * **Update Submission Data** re-shares the contributor's Scenario as it stands now, on top of what was shared before. [Creating & Managing Workflows (For Admins)](/creating-managing-workflows-for-admins/) covers when to use it and when it fails. Each of the three opens a confirmation naming the target status, with an optional comment. What you type there is attached to the entry the action creates under Activity, which makes it the right place to record why you sent a submission back. > **A finished Workflow is read-only.** Once a Workflow has been completed or stopped, all three buttons and the comment box are disabled. The history stays visible, but nothing more can be added to it. ## Activity Activity lists everything that has happened to the submission, newest first. Each line names the person, what they did and when. | You see | What happened | | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | promoted to ‘Preview’ | Someone moved the submission on to that status. | | demoted to ‘Open’ | Someone moved it back to that status. | | updated from ‘Scenario v1’ to ‘Scenario v2’ | The Scenario was re-shared. The two names are the versions before and after; a first share shows only the new one. | | imported ‘Scenario’ into Step ‘Consolidation’ | Someone pulled **this** submission's Scenario into their own step. | | imported ‘Scenario’ from Step ‘EU Base Assumptions’ | **This** submission imported a Scenario from that step. | | a name with text below it | A comment. | > **One import appears on both sides.** When somebody imports your step, the import is recorded on your submission as well as on theirs, under their name. An import you did not make showing up under your own submission is normal: it means a later step has picked up your numbers. ## Commenting on a submission Click ‘Add a comment’ at the top of Activity, type, and click ‘Comment’. The comment appears at the top of the list straight away and cannot be edited or deleted afterwards. You can comment while the Workflow is running if you are a project admin or are assigned to one of the step's states. Everyone else sees the box greyed out. Each comment e-mails everyone holding a permission on one of that step's states, apart from you. Mail goes out on a ten-minute cycle rather than immediately, and it is skipped for anyone who has ticked ‘Disable e-mail notifications’ on their user profile. If nobody on your Workflow ever receives these, e-mail is probably not switched on for your Valsight installation; ask your administrator. The same rules cover the notifications for data updates and status changes, described under Email notifications in [Creating & Managing Workflows (For Admins)](/creating-managing-workflows-for-admins/). --- # Subprocessors URL: https://docs.valsight.ai/subprocessors/ Description: We host our platform primarily within the EU/EEA, apply encryption at rest, and work only with carefully vetted sub-processors that meet rigorous security st… We host our platform primarily within the EU/EEA, apply encryption at rest, and work only with carefully vetted sub-processors that meet rigorous security standards. The table below lists these providers, their processing locations, and the purpose of their services. Where data may be accessed from outside the EEA, we rely on the EU Standard Contractual Clauses and perform transfer impact assessments. We review our sub-processor list regularly and keep this page up to date. | Sub-processor (subcontractor) | Address | Country of processing | Purpose of data processing / description of services | Legal basis for data transfer | | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | | T-Systems International GmbH (Open Telekom Cloud) | Hahnstraße 43d, D-60528, Frankfurt am Main | Germany (Magdeburg; Bördeland/Biere) | Cloud platform (PaaS): virtual machines & databases; data encrypted at rest; provider visibility stops at OSI Layer 4 | No third-country transfer (processing within EU/EEA) | | Hetzner Online GmbH | Industriestr. 25, 91710 Gunzenhausen, Germany | Germany (Falkenstein; Nuremberg) | Cloud platform (PaaS): virtual machines & databases; provider visibility stops at OSI Layer 4 | No third-country transfer (processing within EU/EEA) | | Microsoft Ireland Operations Ltd. (Microsoft Azure) | One Microsoft Place, South County Business Park, Leopardstown, Dublin 18, D18 P521, Irland | Germany (Germany West Central region) | Cloud platform (PaaS): virtual machines & databases; data encrypted at rest (Azure KMS); provider visibility stops at OSI Layer 4; Azure AI used for AI services such as the Valsight AI Assistant | No third-country transfer (processing within EU/EEA) | | Atlassian Corporation (Support Desk / Jira Service Management) | Atlassian Corp.Level 6, 341 George Street, Sydney, NSW , 2000 Australia | EU (Ireland, Germany), Singapore, United States (N. Virginia, N. California, Oregon) | Support desk for ticket handling: email/username/IP and ticket content | International transfers based on EU Standard Contractual Clauses (via Atlassian DPA); TIA available | | Zoho Corporation GmbH, (Site24x7) | Trinkausstr. 7,40213 Düsseldorf, Germany | EU Netherlands (Amsterdam); Ireland (Dublin) | Monitoring of server operations: log files that may include IP addresses and usernames; no access to application data | No third-country transfer (processing within EU/EEA) | Last review: 07 Nov 2025 --- # SUBTRACTION (-) URL: https://docs.valsight.ai/subtraction/ Description: The SUBTRACTION operator subtracts one input from another after aligning both inputs to their common dimensions. In other words, subtraction uses the intersection of the shared dimensions. **Category:** [Arithmetic operators](/arithmetic-operators/) ## Overview The **SUBTRACTION** operator **subtracts one input from another** after aligning both inputs to their **common dimensions**. In other words, subtraction uses the **intersection** of the shared dimensions. The result keeps the **coarser** level in each shared dimension. Dimensions that exist on only one side are aggregated away. Use this operator to calculate differences between two nodes. ## Syntax `'Node1' - 'Node2'` **Example usage:** `'Revenue' - 'OPEX'` ## Parameters | Parameter | Description | Type | Required | | --------- | ------------------------------------------------------------------------------ | -------------- | -------- | | **Node1** | Minuend node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | | **Node2** | Subtrahend node, specified using the node name in single quotes (e.g.`'OPEX'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Dimensionality** | Both inputs are aggregated to their **common dimensions** (the **intersection** of the shared dimensions). Per shared dimension, the **coarser** level is used. Dimensions that exist on only one side are aggregated away. | | **Level values** | Non-matching level values are preserved in the result. | | **Row count** | Equal or reduced, depending on how much aggregation is required before subtracting. | ## Watch out * Subtraction uses the **common dimensions** (**intersection**), just like addition. * Dimensions that exist on only one side are aggregated away before subtracting. * When subtracting a constant such as `'Revenue' - 100`, the node is aggregated first and the constant is then subtracted from the total. * We recommend storing costs as negative values where possible, so addition can be used consistently throughout the model. * Both sides must have the same unit, unless one side is a scalar value. ## Examples ### Subtracting nodes with matching dimensions **Input node:** `'Revenue'` | Year | Value | | ---- | ----- | | 2025 | 500 | | 2026 | 600 | | 2027 | 550 | **Input node:** `'Cost'` | Year | Value | | ---- | ----- | | 2025 | 300 | | 2026 | 350 | | 2027 | 400 | **Formula:** `'Revenue' - 'Cost'` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 500 - 300 | 200 | | 2026 | 600 - 350 | 250 | | 2027 | 550 - 400 | 150 | ### Subtracting nodes with different level values When level values do not overlap, subtraction preserves both values in the result. The value from the second input appears as negative. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 100 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2026 | 40 | **Formula:** `'A' - 'B'` | Year | SUBTRACTION Result | | ---- | ------------------ | | 2025 | 100 | | 2026 | -40 | ### Subtracting nodes with different dimensionality This example shows how subtraction aggregates `Node B` to the common dimensions before subtracting it from `Node A`. **Input node:** `'Node A'` | Year | Value | | ---- | ----- | | 2025 | 5 | | 2026 | 10 | **Input node:** `'Node B'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | A | 2 | | 2026 | A | 3 | | 2026 | B | 4 | **Formula:** `'Node A' - 'Node B'` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 5-2 | 3 | | 2026 | 10-(3+4) | 3 | ## Related | Function | When to use instead | | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | [ADDITION (+)](/addition/) | When you want to combine values across the same shared-level alignment logic but add them instead of subtracting them. | | [MULTIPLICATION (\*)](/multiplication/) | When you want to multiply values instead of subtracting them. | --- # Supported Archiving Methods URL: https://docs.valsight.ai/supported-archiving-methods/ Description: Item Cloud Customers On-Premise Customers / Valsight Corporate Server | Item | Cloud Customers | On-Premise Customers / Valsight Corporate Server | | ----------------------- | ---------------------------- | ------------------------------------------------ | | Projects | Online | Online Offline | | Entire Valsight Content | Automatically done for 1 yr. | Offline Database Backup | ## Online archiving Online archiving means to keep the project and all associated data in the instance, but revoke all access to the project, as outlined here: [Project Rights](/project-rights/). ## Offline archiving Offline archiving means to export the project to a file. Please note that for a complete archive you need to keep the specific version of the Valsight server to import the project. ## Cloud - entire content Valsight keeps daily backups of your entire database for 1 year. Talk to our support to restore a specific backup. ## On-Premise - offline database backup Refer to [Backup & Recovery](/backup-recovery/) to setup an archiving scheme tailored to your needs. --- # Supported Browsers URL: https://docs.valsight.ai/supported-browsers/ Description: Name Version Valsight Support Guideline | Name | Version | Valsight Support Guideline | | --------------- | ------- | ------------------------------------------------------------------ | | Google Chrome | 86+ | 1 year old versions are supported. | | Mozilla Firefox | 68+ | Supported ESR releases. | | Apple Safari | 14+ | The version that is available on the last 2 major Mac OS versions. | | Microsoft Edge | 86+ | 1 year old versions are supported. | More information may be available at Troubleshooting Browser Issues. --- # Table Formatting URL: https://docs.valsight.ai/table-formatting/ Description: Set the table style, resize columns, and control which header cells are merged in a table. Beyond the values it shows, a table has a style, column widths and merged header cells. The first two are set directly, the third follows from the order of the levels. ## What it is Tables use the **Modern** table style by default. Switching to **Classic** changes the look, and the setting also applies to older tables. Columns resize automatically to the best width for the current window. Cells in the table header, or down the left side, are merged where possible. ![A table in the modern style](./images/5621448721.png) ## When to use it * A column is too narrow to read and you want to widen it for good. * The header repeats a value on every column and you want it merged into one cell. * An older table looks different from the rest and should match them. ## Configuration **Style and column widths:** 1. Select the table. In the **Formatting** section of the chart editor, set **Table style** to **Modern** or **Classic**. 2. Drag a column border to resize that column by hand. The width is saved. 3. Double-click a border to reset that column to its initial width, or use **Reset Column Widths** to reset all of them. 4. Switch on **Freeze header columns**, in the **Advanced Formatting** section, to keep the row-header columns in place while a wide table scrolls sideways. ![The table style setting](./images/5620826164.png) ![Resizing a table column by dragging its border](./images/5621252109.png) **Merged cells:** Which cells merge depends on the order of the levels, so place them in the intended order in the **Configure Axes** dialog. In the example below, **Country** is placed above **City** and **Year** above **Quarter**, which displays the upper levels as merged cells and adds columns with totals. | Configure Axes | Table | | ------------------------------------------------------------------ | ------------------------------------------------------------------------- | | ![Configure axes with Country above City](./images/5094191034.png) | ![The resulting table with merged Country cells](./images/5094191154.png) | | ![Configure axes with Year above Quarter](./images/5094191049.png) | ![The resulting table with merged Year cells](./images/5094191039.png) | ## Good to know * **Levels have to belong to the same dimension to be merged.** The example uses the dimension Location with the levels Country and City, and the dimension Time with Year and Quarter. * **A hand-set column width sticks.** Automatic sizing stops applying to that column until you double-click its border to reset it. * **A very wide table shows a warning instead of its data.** Above the column limit, 120 by default, the table renders a callout naming the limit and the number of columns rather than the data itself. Reduce the columns with filters or a coarser level, or ask an administrator to raise the limit. See [Limitations & Data Sizing Guidelines](/limitations-data-sizing-guidelines/). * **Row formats are set elsewhere.** Subtotals, totals and indentation live in the **Style Columns and Rows** dialog: see [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/). ## Related * [Styling Data Series, Columns and Rows](/styling-data-series-columns-and-rows/): subtotal and total formats, indentation, colors. * [Sorting Level Values](/sorting-level-values/): the order the rows and columns appear in. * [Data Display in Charts and Tables](/data-display-in-charts-and-tables/): which data a table shows, and at which aggregation. --- # Target Value Setting URL: https://docs.valsight.ai/target-value-setting/ Description: In this article, you will learn what the target setting function does and how to use it. In this article, you will learn what the target setting function does and how to use it. * You can insert target values instead of change values into line-items * It is possible to upload an XLSX file to set the target values of a line-item * Inserting a target value causes Valsight to calculate the necessary change from the baseline value * Target value setting allows you to insert expected outcome values ## Target value setting When configuring a line-item, there are two options for entering simulation values. The first option for setting target values is to enter values into the “Change” column. This causes Valsight to calculate the change value as a delta on top of the corresponding node’s baseline. The resulting calculated value will be displayed in the “Result” column. The second option is to enter target values directly into the “Result” column; this is called “Target Setting”. This results in Valsight calculating the difference compared to the baseline value and automatically displaying the obtained delta in the “Change” column. Setting a target value instead of a change value has a few key advantages when configuring line-items. The first advantage is that certain drivers of a business model are commonly handled in terms of expected outcomes. Factors like the number of employees might be viewed with an expected target number instead of a change to the current value. Another advantage is that the necessary change values will be calculated automatically. This can help in demonstrating the necessary actions in order to achieve certain goals. This can enable a business to set expectations in a realistic and achievable frame. ## How to set target values To set a target value, open a line-item’s detail view in the Scenario Manager by clicking on its name. From there, you can select any cell in the “Result” column and enter a target value by typing it in and confirming with the “Enter” key. ![Opening Detail View.gif](./images/5094230956.gif)![Target Value Setting.gif](./images/5094230317.gif) ## Using an XLSX import to set target values If your data is already available as a Target Value, you don't need to calculate the respective delta for the Valsight import. Download the Excel Sheet of your particular Line-Item and change the header from "Change" to "Target". ("Zielwert" in German, both are recognized independent of the language setting). ![image-20220222-142810.png](./images/6988202009.png) To upload an XLSX file, open the line-item’s three-dot menu and select “Upload Excel”. ![Uploading XLSX.png](./images/5094230329.png) This will open the following dialog, which lets you select the file for the upload: ![image-20220822-074927.png](./images/5094230321.png) Select the desired file and click “Upload” to finalize the process. Afterward, your target values are imported and changes to your existing baseline are calculated automatically. Missing rows from your upload which are present in the baseline will result in 0 as the final (target) value, i.e. your absolute change will be the negative value of your original value. > **Note:** > > Be aware that a target upload is only supported for absolute values. --- # Technical & Minor Version Release Notes URL: https://docs.valsight.ai/technical-minor-version-release-notes/ Description: A comprehensive list of all technical information regarding new releases. Includes warnings, which usually have implications on existing models and settings,… A comprehensive list of all technical information regarding new releases. Includes warnings, which usually have implications on existing models and settings, as well as general technical information. ## 7.1.0 *Major* ### API changes No API Changes ### Warnings * `parameterEffectProxy` Node Property Removed from ModelDSL (MEDIUM) The node property `parameterEffectProxy` no longer exists in ModelDSL. Uploading a ModelDSL containing this property will result in a crash. If your ModelDSL includes `parameterEffectProxy`, it can be safely deleted as its functionality was removed in a previous version. * **ROLLUP Function No Longer Accepts Dimension Names as Input Parameters (HIGH)** The ROLLUP function signature now requires Level names only and no longer accepts Dimension names. Example: Before: `ROLLUP("Node 1", "Time", "Year")`, After: `ROLLUP("Node 1", "Year")`. The release will automatically migrate all existing ROLLUP usages to the new syntax. Note: including a Dimension name will now cause the function to fail. Edge cases requiring manual updates after migration: ROLLUP calls inside comments will not be updated; if ROLLUP inputs span multiple lines with a comment on the Dimension line, the comment will shift up one line after migration. * **Removal of Not Supported Endpoints (LOW)** The endpoints `POST /v1/perspectives` and `DELETE /v1/perspectives` have been removed. These endpoints were never officially supported. To modify the perspectives of a perspective chart, use `PUT /simulationCharts/{id}/updatePerspectives` instead. ## 7.0.1 *LTS - Hotfix* ### API changes * **Removal of Chart Thumbnail Endpoints (LOW)** The endpoints for chart thumbnails (`GET /simulationCharts/{id}/thumbnail`, `POST /simulationCharts/{id}/thumbnail`, `DELETE /simulationCharts/{id}/thumbnail`) have been removed as they were not in use. Image charts and perspectives are unaffected. ### Warnings No Warnings ## 7.0.0 *LTS* ### API changes * **Removal of Global Parameter Effects Endpoints (LOW)** The REST endpoint `GET /simulationWorkspaces/{id}/parameterEffects` and WebSocket endpoint `/simulation/parameterEffects` have been removed. These endpoints returned global parameter effects per workspace. * **Removal of Legacy Snapshot Workspace Endpoint (LOW)** The endpoint `POST /simulationWorkspaces/{workspaceId}/snapshot` has been removed. ### Warnings * **Presentation Mode Disabled by Default (HIGH)** Presentations (Workspace Snapshots) are now disabled by default via the new configuration flag `featureFlags.presentationModeEnabled`. On fresh deployments, this flag is set to `false`. On existing instances, it is set to `true` only if snapshots exist in the database. The flag cannot be modified via the Settings page; it requires a direct API call or database access. When `false`, creating new snapshots in the Scenario Manager is disabled and Presentation management UI pages are inaccessible. * **Operation per Scenario Renamed to Operation per Baseline (MEDIUM)** The feature previously known as “Operation per Scenario” has been renamed to “Operation per Baseline” across the UI and ModelDSL. Any ModelDSL using the old property name will need to be updated to reflect this rename. * **Scenarios Renamed to Baselines (MEDIUM)** Scenarios have been renamed to Baselines throughout the application. This affects UI labels, API parameter names, and ModelDSL properties. Review any integrations or scripts that reference “scenario” terminology. ## 6.16.0 *Major* No API Changes or Warnings ## 6.15.0 *Major* **API Changes (MEDIUM)** Removal of legacy endpoint for adding calculated nodes **Removal of model and workspace lock endpoints (MEDIUM)** Removal and replacement of chart and line-item lock endpoint * Endpoint `DELETE /simulationNodes/{id}/lock` has been replaced with `DELETE /simulationNodes/{id}/locks` (plural). * Endpoints for locking/unlocking a workspace (`POST /simulationWorkspaces/{id}/lock`, `DELETE /simulationWorkspaces/{id}/lock`) have been removed. * Endpoints for locking/unlocking a model (`POST /simulationModels/{id}/lock`, `DELETE /simulationModels/{id}/lock`) have been removed. * Endpoint `DELETE /simulationLineItems/{id}/lock` has been replaced with `DELETE /simulationLineItems/{id}/locks` (plural). ## 6.14.0 *Major* No API Changes or Warnings ## 6.13.0 *LTS - Major* **API Changes (MEDIUM)** * **Removal of Management UI Theme API Endpoints (MEDIUM)** The following endpoints for managing UI themes have been removed: `GET /api/v1/ui-themes`, `GET /api/v1/ui-themes/{id}`, `POST /api/v1/ui-themes`, `PATCH /api/v1/ui-themes/{id}`, `DELETE /api/v1/ui-themes/{id}`. UI theming is no longer supported. **Warnings** * **Support for IE 11 Discontinued (HIGH)** Valsight no longer supports Internet Explorer 11. Users accessing Valsight via IE11 will experience degraded or broken functionality. Administrators should ensure all users have migrated to a supported browser. * **Minimum Java Version Increased to Java 11 (HIGH)** Valsight now requires a minimum of Java 11. Instances running on Java 8 must be upgraded before deploying this version. View the full feature notes here: ## 6.12.0 *Major* **API Changes:** * **Removal of Simulation Space Category Endpoints (MEDIUM)** The category endpoints for simulation spaces have been removed: `GET /simulationSpaces/categories`, `POST /simulationSpaces/categories`, `PATCH /simulationSpaces/categories/{id}`, `DELETE /simulationSpaces/categories/{id}`. Project categorization is no longer supported via these endpoints. **Warnings** * **Session Token Format Changed (MEDIUM)** The session token format has changed. Existing active sessions will be invalidated after the upgrade. All users will need to log in again after the update is applied. * **User Directory Sync Behavior Change (MEDIUM)** The user directory synchronization now runs on a fixed schedule rather than on-demand. Administrators relying on immediate sync behavior should review their user provisioning processes. * **PDF Export Engine Updated (LOW)** The PDF export engine has been updated. Minor visual differences in exported PDFs may be observed. No action required. View the full feature notes here: ## 6.11.0 *Major* **API Changes:** * **Removal of Legacy Login Endpoint (LOW)** The legacy login endpoint `POST /api/v1/login` has been removed. Authentication must now use the current `POST /api/v1/auth/login` endpoint. **Warnings** * **PostgreSQL Minimum Version Updated (HIGH)** The minimum supported PostgreSQL version has been increased. Instances running on older PostgreSQL versions must be upgraded before deploying this release. * **LDAP Configuration Key Renamed (MEDIUM)** The LDAP configuration property key has been renamed. Existing LDAP configurations must be updated to use the new key name to ensure continued authentication. View the full feature notes here: ## 6.10.0 *Major* **Warnings:** **API Changes:** **Removal of Bulk Update Sheets Endpoint (HIGH)** * The `PATCH /simulationSheets` bulk update endpoint has been removed. Sheet updates must now be performed individually using `PATCH /simulationSheets/{id}`. **Modification of Simulation Workspace Sheet Endpoints (HIGH)** * The response format of the workspace sheet endpoints has been modified. Clients consuming `GET /simulationWorkspaces/{id}/sheets` must be updated to handle the new response structure. ## 6.9.0 *LTS - Major* **API Changes:** * **Removal of deprecated project export/import endpoint (MEDIUM)** The endpoint POST /`simulationSpaces/{id}/import` has been removed (it has been deprecated since 6.4.0). Use POST /simulationSpaces/{id}/export and POST /simulationSpaces/import instead. **Warnings:** * **Migration of Hardcoded Port 8080 to Dynamic Port (HIGH)** The internal server port is no longer hardcoded to 8080. Reverse proxy configurations and firewall rules referencing port 8080 must be reviewed and potentially updated. * **Library Update: Hibernate (HIGH)** Hibernate has been updated to a new major version. Model DSL files or custom integrations relying on internal Hibernate behavior or entity field naming conventions may require review. * **Change to SAML Configuration for Multi-Tenant Setups (MEDIUM)** SAML-based authentication configuration for multi-tenant instances has changed. Customers using SAML SSO in multi-tenant environments must update their configuration before upgrading. View the full feature notes here: ## 6.8.0 *Major* No API Changes or Warnings ## 6.7.0 *Major* No API Changes or Warnings ## 6.6.0 *LTS - Major* No API Changes or Warnings ## 6.5.0 *Major* No API Changes or Warnings ## 6.4.0 *LTS - Major* No API Changes or Warnings ## 6.3.0 *Major* No API Changes or Warnings ## 6.2.0 *LTS - Major* No API Changes or Warnings ## 6.1.0 *Major* No API Changes or Warnings ## 6.0.0 *LTS - Major* No API Changes or Warnings ## 5.7.0 *Major* No API Changes or Warnings ## 5.6.0 *LTS - Major* No API Changes or Warnings ## 5.5.0 *Major* No API Changes or Warnings ## 5.4.0 *LTS - Major* No API Changes or Warnings ## 5.3.0 *LTS - Major* No API Changes or Warnings ## 5.2.0 *Major* No API Changes or Warnings ## 5.1.0 *LTS - Major* No API Changes or Warnings ## 5.0.0 *LTS - Major* No API Changes or Warnings --- # Template Manager URL: https://docs.valsight.ai/template-manager/ Description: The Template Manager can be found through the tab in the top right corner of the Export Manager and allows users to manually create customized export templates. The Template Manager can be found through the tab in the top right corner of the [**Export Manager**](/export-manager/) and allows users to manually create customized export templates for the desired use case. These templates allow a more flexible node selection when exporting scenarios, but also provide a standardized frame for recurring exports. These templates are saved and editable in the template manager. Templates can lead to a reduced number of data exported, which leads to slower loading times. > The template manager needs write access to the respective project **and** a user type of **Simulator**, **Modeler** or **Unrestricted**. (More on user types and access rights [can be found here](/licenses-user-types-access-management/).) ## Step-by-Step approach 1. Template Manager Navigate to the template manager via the ‘Templates’ tab in the top right corner of the Export Manager. When you use the manager for the first time, an empty space will be shown. ![image-20240405-151926.png](./images/5551783971.png) 2. Create a template After using 'Create a Template', a dialog opens that allows you to enter a name for your template and a description (optional). ![image2021-11-23\_17-6-26.png](./images/5094209155.png) 3. Models and nodes In the third step, you can customize your template based on your needs and preferences. All models and nodes accessible to you are shown below. Select the nodes that should be included in the export. To simplify your choice, you have the option to 'Only show nodes marked for export'. Nodes can be [marked for export](/data-upload-import-export-overview/) in the node editor. With the search function, you can specifically look for certain nodes and select those. After selecting the relevant nodes, 'Finish' will create the template. ![image2021-11-23\_17-7-35.png](./images/5094209143.png) 4. Templates After creating a template, it will be listed in the template manager with information about the creator, the date created, and the last change. ## Edit existing templates A template can still be edited after creation. To do so, navigate to the template manager, and click on 'Edit' in the Actions menu. In this menu, templates can also be deleted. ## What templates can be used for The template manager has been integrated to simplify export processes and to avoid including all accessible nodes. Therefore, the template manager can be used to export all kinds of Valsight-specific data and their nodes. So far, this can be exported: | template usage | Available Since | | ---------------- | --------------- | | Scenario exports | **5.2.0** | ## Usage of templates An example of how to use templates would be to export a scenario based on one. To export a scenario, navigate to your workspace via the navigation bar and open the Scenario Manager. Open the “Export Scenario” dialog by clicking on the corresponding button. ![Exporting Scenario.png](./images/5094216716.png) In the “Export Scenarios” dialog, the first step is about choosing your export format. In the second step, you can now choose one of the previously created templates in the dropdown. The export based on a certain template will then include all activated nodes automatically, without the need for users to go through all nodes and models every time an export should be made. To finalize your export, navigate to the summary step and use ‘Finish’. ![Exporting with Template.png](./images/5094217035.png) ## Related * [Export Manager](/export-manager/) --- # Time Bridges URL: https://docs.valsight.ai/time-bridges/ Description: A time bridge explains the change between two or more points in time within one scenario, using the effects of assumptions and line-items. A time bridge explains the change between two or more points in time within one scenario. It steps from the earlier period's value to the later one through the effects of the assumptions and line-items in between. ## What it is A time bridge answers "why is this year different from last year". Its counterpart, the [scenario bridge](/scenario-bridges/), answers "why is this scenario different from that one" within a single period. Both use the staircase the chart editor calls a **waterfall chart**. ![A time bridge stepping from one year's value to the next through the effects in between](./images/5286264876.png) ## When to use it * You want to explain year-over-year movement to someone who only sees the two totals. * You want to separate what the plan assumed from what the model itself contributed. * You want to show the effects of several years accumulating, rather than one step at a time. Use a **[scenario bridge](/scenario-bridges/)** instead when the two values are two scenarios in the same period. ## Configuration ### Create the bridge 1. Click the **Chart** button in the upper right corner of a worksheet. 2. Select **Time Bridge** in the chart selection. 3. Select the node that should be the base of the data. 4. Select a scenario and the time level to bridge across, for example **Year**. 5. Select the periods to compare. 6. Select what the difference should be broken down by. **Assumptions** is preselected. ![The time bridge configuration, with a node and a scenario selected](./images/5285511242.png) ### Change it afterwards | Setting | What it does | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Node** | The node whose data the bridge shows. Change it in the chart editor at any time. | | **Scenario** | The scenario the change is analyzed within. A time bridge works inside one scenario. | | **Configure Axes** | Puts line-items or assumptions on the axis. A new bridge carries the time level you chose as the data series, and the breakdown you chose, **Assumptions** by default, on the x-axis. | | **Period Selection** | Which periods the bridge spans. Set through the **Time** filter in the chart editor. | A bridge spans the periods you picked when creating it. Change them afterwards through the **Time** filter: * Selecting two non-adjacent periods, for example 2017 and 2020, produces a bridge with the summed-up effects of the years in between. * Selecting a single period makes the bridge use the previous period as its reference point automatically. You can switch an existing chart between the two bridge types with **Bridge between periods** in **Bridge Settings**. ![The Bridge between periods option in the bridge settings](./images/5286101035.png) ### Add intermediate sums A bridge can show intermediate sums as gray bars, so a long chain of effects is broken up by the running total at chosen points. To show 2020, 2021, 2022 and 2023 as intermediate sums in this chart: ![A bridge with gray intermediate sum bars between the effects](./images/5166170171.png) Add them as years in the sidebar: ![Adding years in the sidebar to create intermediate sums](./images/5166170177.png) ## How the effects are calculated Assumptions come in two kinds, and the difference decides what a time bridge shows. An assumption **with a base effect** carries its adjustment into the following years. One **without a base effect** is a one-time adjustment that does not. Take the node **Revenue**. Assumptions without a base effect, each year adjusted on its own: | | 2017 | 2018 | 2019 | | --------------------------------- | ---- | ---- | ---- | | **Assumption 1** (no base effect) | +10 | +15 | +20 | | **Assumption 2** (no base effect) | - | +20 | - | | Revenue | 10 | 35 | 20 | Assumptions with a base effect, where the previous year carries forward: | | 2017 | 2018 | 2019 | | ----------------------------------- | ---- | ---- | ---- | | Revenue PY | - | 20 | 35 | | **Assumption 3** (with base effect) | +10 | - | - | | **Assumption 4** (with base effect) | +10 | +15 | +20 | | Revenue | 20 | 35 | 55 | Valsight determines the individual effect of every assumption active in the selected scenario between the two periods being viewed. For the data above, a time bridge for 17/18 or 18/19 shows: | | Time Effect 17/18 | Time Effect 18/19 | | ----------------------------------- | ----------------- | ----------------- | | **Assumption 1** (no base effect) | +5 | +5 | | **Assumption 2** (no base effect) | +20 | -20 | | **Assumption 3** (with base effect) | 0 | 0 | | **Assumption 4** (with base effect) | +15 | +20 | Assumption 3 contributes nothing to either step: its adjustment landed in 2017 and, because it has a base effect, it is carried in both years of each comparison and cancels out. ## Good to know * **A base effect can make an assumption disappear from the bridge.** An assumption whose adjustment is already carried in both periods nets to zero, as Assumption 3 does above. That is correct, not a missing effect. * **A one-time assumption shows up twice, with opposite signs.** Assumption 2 adds +20 in 17/18 and -20 in 18/19, because the adjustment arrives and then goes away again. * **Two non-adjacent periods sum the years between them.** Selecting 2017 and 2020 does not skip 2018 and 2019, it accumulates them. * **The model's own contribution is separate from the assumptions.** It arrives as a single data effects block, which can be split per node or grouped. See [Data Effects Display in Bridge](/data-effects-display-in-bridge/). * **Assumptions can explain themselves on hover.** Give an assumption a description and switch on **Show descriptions in tooltips**. See [Showing assumption descriptions](/assumption-effects/#showing-assumption-descriptions). ## Related * [Data Effects Display in Bridge](/data-effects-display-in-bridge/): splitting the model's own contribution out of its single block. * [Scenario Bridges](/scenario-bridges/): the same staircase, explaining a difference between scenarios. * [Assumption Effects](/assumption-effects/): how each effect is derived, and how to show descriptions on hover. * [Grouping Assumption Effects](/grouping-assumption-effects-in-bridges/): combine the line-items of one assumption into a single bar. --- # The time dimension URL: https://docs.valsight.ai/time-dimension/ Description: Time is the one dimension Valsight generates for you, with its levels and level values derived from the project's time horizon. Time is the one dimension you never create. Valsight generates it for every project, derives its level values from the project time horizon, and regenerates them when the horizon changes. That makes it behave differently from the dimensions you build yourself, which matters before you upload data, write a formula, or pick a chart level. For the vocabulary used below (dimension, level, level value, hierarchy) see [How dimensions work](/how-dimensions-work/). ## How it is generated The project time horizon defines the start and end of the planning period. Valsight walks every date in that range and derives one level value per level from each date, so the levels are always complete and always consistent with one another. Two consequences matter in practice: * You cannot add or remove time level values by hand. Change the horizon instead, see [Changing the Time Horizon](/changing-the-time-horizon/). * A date outside the horizon has no level value, so uploading data for it raises an error rather than extending the dimension. ## Levels Every time dimension starts with an `ALL` level that aggregates the whole horizon. Below it sit the levels that carry dates, and a project uses one of two structures for them. The month-based structure is the default: | Level | Level value shape | Example | | ------- | --------------------------------- | -------- | | Year | four-digit year | 2025 | | Quarter | year, hyphen, `Q`, quarter number | 2025-Q4 | | Month | year, hyphen, two-digit month | 2025-01 | | Day | eight digits, no separators | 20250101 | The week-based structure replaces Quarter and Month with a single Week level: | Level | Level value shape | Example | | ----- | ------------------------------------- | -------- | | Year | four-digit ISO week-based year | 2025 | | Week | year, hyphen, `W`, two-digit ISO week | 2025-W04 | | Day | eight digits, no separators | 20250101 | Which structure a project uses is a project property, set when the project is created and changeable afterwards. Two things are worth knowing before changing it: * In a week-based project the top level is still named `Year`, but it holds the **ISO week-based** year. Early January can therefore belong to the previous year, because a week is never split across two years. * Switching an existing project from month-based to week-based **deletes its Quarter and Month levels** and unlinks the CalendarMonth dimension; switching back deletes the Week level. Either direction also clears the horizon overrides on every model and workspace. Anything referencing the removed levels stops resolving, so this is not a setting to revisit casually. ## How time columns are loaded from Excel On upload, Valsight links a column to a time level by its header name. Alongside the level names above it accepts a set of aliases, and header case and surrounding spaces do not matter. See [Recognized Column Names](/recognized-column-names/) for the full list and the value format each level expects. ## Companion dimensions Two other dimensions deal with time without being part of it: * **CalendarMonth** holds the months `01` to `12` without a year and is linked to the Month level, so you can compare the same month across years. Optional, see [Calendar Months Dimension](/calendar-months-dimension/). * **Sequence** describes abstract steps relative to a starting point ("Year 0", "Year 1") rather than calendar dates, for models such as depreciation or ramp-up curves. See [Configure the Sequence Dimension](/configure-the-sequence-dimension/). ## Related * [How dimensions work](/how-dimensions-work/): the vocabulary and mental model behind every dimension * [Changing the Time Horizon](/changing-the-time-horizon/): the setting that drives which level values exist * [Project Settings](/project-settings/): **Divide years into** is where the calendar is chosen, and therefore where the shape above is decided * [Recognized Column Names](/recognized-column-names/): the column headers an upload links to time levels automatically * [Calendar Months Dimension](/calendar-months-dimension/): comparing the same month across years --- # TIMELAG URL: https://docs.valsight.ai/timelag/ Description: The TIMELAG function calculates time-lagged effects on a chosen time granularity, distributing each input value over future periods according to a lag profile. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **TIMELAG** function **calculates time-lagged effects on a chosen time granularity.** Each value from the input node is distributed over future periods according to a lag profile. Multiple contributions can overlap when several input values are lagged into the same period. Use this function when an effect should show up gradually or with a delay across time periods, for example to model delayed investment effects or gradual impact curves. ## Syntax `TIMELAG('ValueNode', 'TimeLagNode', "TimeLevel")` **Example usage:** `TIMELAG('Investment', 'TimeLagNode', "Year")` ## Parameters | Parameter | Description | Type | Required | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | -------- | | **Value Node** | Input node with the values that should be time-lagged. Must have the selected time level. | Node reference | Yes | | **TimeLag Node** | Node containing values between `0` and `1` (= 100%) on the `Sequence` dimension, defining how the lag is applied. Sequence entry `0` refers to the impact in the base year. This node should not have the selected time level. | Node reference | Yes | | **Time Level** | Name of the time level where one time-level step equals one sequence step, specified in double quotes (e.g.`"Year"`) | Level name | Yes | ## Output shape | Aspect | Behavior | | -------------- | ----------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Preserves the non-time levels of the Value Node. The time level is set as specified. | | Values | Each input value is multiplied by the lag input and spread across future periods. Overlapping contributions are summed. | | Row count | Typically increases, as each input value generates multiple output rows across the lag window. | ## Watch out * The Value Node must have a time level at least as fine-grained as specified in the function. * The TimeLag Node must **not** contain any time level. * The TimeLag Node cannot be more fine-grained than the Value Node on non-sequence levels. * Beyond the last defined sequence entry, the **last lag value is repeated indefinitely**. If the last entry is `0.75`, the contribution permanently stays at 75%. It does not automatically reach 100%. * Gaps in the sequence (e.g. entries at 0, 1, 2, 4 but not 3) are treated as **zero**. * If the sequence does not start at `0`, position 0 defaults to zero. * If the TimeLag Node has no matching lag profile for a given category, the output for that category is **zero** (not the original values). * If the Value Node has data at a finer time level than the specified Time Level (e.g. monthly data with `"Year"`), values are automatically aggregated before the lag is applied. ## Examples ### Distributing a single value with a gradual ramp-up This example shows how a single investment is gradually phased in over time. 20% of the effect is felt immediately, 50% after one year, and the full effect is reached after two years. **Input node:** `'Cost'` | Year | Cost | | ---- | ---- | | 2025 | 100 | **Input node:** `'LagProfile'` | Sequence | Effect | | -------- | ------ | | 0 | 0.2 | | 1 | 0.5 | | 2 | 1 | **Formula:** `TIMELAG('Cost', 'LagProfile', "Year")` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 100 × 0.2 | 20 | | 2026 | 100 × 0.5 | 50 | | 2027 | 100 × 1 | 100 | The effect ramps up from 20% to 100% over two years. From 2027 onward, the full value persists because the last sequence entry (`1`) repeats indefinitely. ### Overlapping contributions from multiple input periods This example shows how investments are distributed over future years based on a lag profile. The lag profile gradually releases each investment amount over three sequence steps, so later years can contain overlapping contributions from multiple inputs. **Input node:** `'Investment'` | Year | Investment | | ---- | ---------- | | 2025 | 10 | | 2026 | 0 | | 2027 | 15 | | 2028 | 0 | **Input node:** `'TimeLagNode'` | Sequence | Effect | | -------- | ------ | | 0 | 0 | | 1 | 0.25 | | 2 | 0.5 | | 3 | 1 | **Formula:** `TIMELAG('Investment', 'TimeLagNode', "Year")` | Year | Calculation | Result | | ---- | ------------------ | ------ | | 2025 | 10 × 0 | 0 | | 2026 | 10 × 0.25 | 2.5 | | 2027 | 10 × 0.5 | 5 | | 2028 | 10 × 1 + 15 × 0.25 | 13.75 | | 2029 | 10 × 1 + 15 × 0.5 | 17.5 | | 2030 | 10 × 1 + 15 × 1 | 25 | From 2028 onward, both the 2025 investment (at full effect) and the 2027 investment (ramping up) contribute to the result. ### Different lag profiles per category The TimeLag Node can include non-sequence dimensions to define separate lag curves per category. Here, Category A ramps up in one year while Category B ramps up over three years. **Input node:** `'Investment'` | Year | Category | Investment | | ---- | -------- | ---------- | | 2025 | A | 100 | | 2025 | B | 100 | **Input node:** `'LagProfile'` | Sequence | Category | Effect | | -------- | -------- | ------ | | 0 | A | 0.5 | | 1 | A | 1 | | 0 | B | 0 | | 1 | B | 0.25 | | 2 | B | 0.5 | | 3 | B | 1 | **Formula:** `TIMELAG('Investment', 'LagProfile', "Year")` | Year | Category | Calculation | Result | | ---- | -------- | ----------- | ------ | | 2025 | A | 100 × 0.5 | 50 | | 2026 | A | 100 × 1 | 100 | | 2025 | B | 100 × 0 | 0 | | 2026 | B | 100 × 0.25 | 25 | | 2027 | B | 100 × 0.5 | 50 | | 2028 | B | 100 × 1 | 100 | Category A reaches full effect after one year. Category B ramps up gradually over three years. The lag profile node can also use a coarser level than the Value Node (e.g. `Product Group` on the lag profile while the Value Node has `Product`). Child values inherit the parent's lag curve. ### Temporary effect with a zero-ending sequence If the last sequence entry is `0`, the contribution decays to nothing permanently. This models impulse or temporary effects that fully disappear after a defined period. **Input node:** `'Campaign'` | Year | Campaign | | ---- | -------- | | 2025 | 100 | **Input node:** `'LagProfile'` | Sequence | Effect | | -------- | ------ | | 0 | 0 | | 1 | 1 | | 2 | 0.5 | | 3 | 0 | **Formula:** `TIMELAG('Campaign', 'LagProfile', "Year")` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 100 × 0 | 0 | | 2026 | 100 × 1 | 100 | | 2027 | 100 × 0.5 | 50 | | 2028 | 100 × 0 | 0 | The effect peaks in 2026, decays to half in 2027, and disappears completely from 2028 onward. Because the last sequence entry is `0`, the contribution stays at zero permanently. ## Related | Function | When to use instead | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | [STRETCH\_CURVE](/stretch-curve/) | When you want to stretch or compress a defined profile along the axis instead of applying a delayed effect over time. | | [SCHEDULEPROJECTS](/scheduleprojects/) | When you want to place project blueprints onto actual start periods instead of distributing an existing value with a lag profile. | | [SHIFT](/shift/) | When you need to move existing values by a direct offset along a time level instead of distributing them with a lag profile over multiple periods. | --- # Training URL: https://docs.valsight.ai/training/ Description: Der Trainingsbereich bietet umfassende Tutorials, die Schritt für Schritt durch verschiedene Funktionen der Software führen. Diese Anleitungen ermöglichen es… Der Trainingsbereich bietet umfassende Tutorials, die Schritt für Schritt durch verschiedene Funktionen der Software führen. Diese Anleitungen ermöglichen es, sich gezielt mit den wesentlichen Aspekten der Software vertraut zu machen. --- # Export-Manager URL: https://docs.valsight.ai/training-export-manager/ Description: Diese Seite bietet Tutorials und Anleitungen rund um das Thema Export Manager. Diese Seite bietet Tutorials und Anleitungen rund um das Thema Export Manager. ## Export Manager Video: [Export Manager](https://www.youtube.com/watch?v=4R125D7a2TY) In diesem Tutorial erfährst du, wie du den Export Manager in Valsight nutzt, um Szenario-Exporte zentral zu verwalten. Wir zeigen dir, wie du Exporte erstellst, mit Templates arbeitest, den Status von Exporten überprüfst und diese versionierst. Außerdem lernst du, wie Exporte mit anderen Projekten geteilt werden. Verstehe, wie du Exporte herunterlädst, bearbeitest und stets auf dem neuesten Stand hältst. [Mehr Details](/export-manager/) ## Projekte verbinden mit Szenario Exporten Video: [Projekte verbinden mit Szenario Exporten](https://www.youtube.com/watch?v=Y2AZsEEdMWA) In diesem Tutorial zeigen wir dir, wie du Exporte für andere Projekte freigibst, Exportszenarien in Zielprojekte importierst und simulierte Knoten in neuen Projekten nutzen kannst. Erfahre außerdem, wie du Exporte aktualisierst und deine Datenquellen immer auf dem neuesten Stand hältst. [Mehr Details](/importing-scenarios/) und [Exporte freigeben](/sharing-exports/) --- # Trainingsmodelle - Modelle URL: https://docs.valsight.ai/trainingsmodelle-modelle/ Description: Hier befinden sich Trainingsmodelle zum Nachbauen Hier befinden sich Trainingsmodelle zum Nachbauen --- # Troubleshooting guide URL: https://docs.valsight.ai/troubleshooting-guide/ Description: Use this guide when a node formula returns unexpected results, for example empty output, wrong granularity, or wrong numbers. Use this guide when a **node formula returns unexpected results**, for example empty output, wrong granularity, or wrong numbers. Find the symptom that matches what you see in [Data Preview](/data-preview-of-nodes/), then work the problem to track down the cause. ## Find your symptom | Step | Detail | | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Empty output | Values are missing where you expect data. If you use `FILTER`, confirm the dimension names, level values, and the intended level all match exactly; and check whether one input is missing values where the other is defined. | | Wrong shape | The result is too aggregated or too granular. Too aggregated: check whether `+` or `-` collapsed the inputs to their common dimensions, and make it explicit with `ROLLUP` or `ROLLUP_TO`. Too granular: check whether `*`, `/`, or `EXPAND` added detail. | | Right shape, but zeros where you expected `N/A` | A missing operand is usually turned into a defined value rather than staying undefined. `*` gives `0` when exactly one factor is missing; `/` and `%` give `0` for a missing dividend, but `N/A` for a missing or zero divisor; `+` and `-` treat a missing side as `0` and give `N/A` only when both sides are missing; every comparison and boolean operator reads a missing side as `0` and always returns `0` or `1`. Use [IS\_NA](/is-na/) to test for missing values and [FILLMISSING](/fillmissing/) to decide what they become. | | Wrong numbers | The shape is right but the values are off. Check constants such as `+ 1` (use `ADDEACH` for element-wise adjustments), whether assumptions or scenarios changed the result upstream (consider `BASELINE` or `NONSIM`), and whether operator order matters. | ## Work the problem | Step | Detail | | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Define the expected result | Note one specific intersection you expect to be correct and the expected output shape, including dimensions and levels. This gives you something to check against. | | Fix syntax and validation errors first | Resolve any [validation](/validations/) or syntax error the editor flags before you touch the formula logic, then re-check in [Data Preview](/data-preview-of-nodes/). | | Simplify by bisection | Start from a single node reference such as `'Sales'`, then add the parts back one at a time. Move large sub-expressions into helper nodes so you can inspect them. | | Spot-check the result | Confirm at least two representative intersections, checking both the shape and the values, so you don't fix one case while breaking another. | | Clean up | Once the result is correct, split complex logic into helper nodes where it helps and add short `#` comments to clarify intent. | ## Still need help? Contact Valsight Customer Support: ## Related * [Formula basics](/formula-basics/): syntax rules, constants, and how formulas evaluate * [Operators](/operators/): arithmetic, comparisons, and alignment behavior * [Function catalog](/function-catalog/): A-Z index and categories for detailed behavior * [Browse by category](/browse-by-category/): choose the right function family by intent --- # TRUE URL: https://docs.valsight.ai/true/ Description: The TRUE function returns 1 for every defined value in the input node. Undefined intersections remain undefined in the result. **Category:** [Logical functions](/logical-functions/) ## Overview The **TRUE** function **returns 1 for every defined value in the input node**. Undefined intersections remain undefined in the result. Use this function when you need a constant true flag across all defined intersections of an input node, for example as a condition in IF or to create a binary helper table. ## Syntax `TRUE('Node')` **Example usage:** `TRUE('Revenue')` ## Parameters | Parameter | Description | Type | Required | | --------- | ---------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | ------------------------------------------------------------------------------------- | | Dimensionality | Same as input. | | Values | **1** for every defined intersection. Undefined intersections remain undefined (N/A). | | Row count | Same as input. Only defined rows produce output. | ## Watch out * TRUE only covers **defined rows**. It does not create values where the input is undefined. If you need to flag undefined rows, use [IS\_NA](/is-na/) instead. * The input value itself does not matter. TRUE returns 1 regardless of whether the value is positive, negative, or zero. Only whether the value is defined matters. * TRUE accepts expressions as input (e.g. `TRUE('A' + 'B')`). The result reflects the dimensionality and defined intersections of the combined expression. ## Examples ### Returns 1 for all defined rows This example shows TRUE returning `1` for every row that has a defined value in the input node. **Input node:** `'Revenue'` | Year | Value | | ---- | ----- | | 2025 | -24.5 | | 2026 | 95 | | 2027 | 110 | **Formula:** `TRUE('Revenue')` | Year | TRUE Result | | ---- | ----------- | | 2025 | 1 | | 2026 | 1 | | 2027 | 1 | ### TRUE applied to a combined expression This example shows TRUE applied to a sum of nodes. It returns `1` for each year where the combined expression produces a defined value. **Input node:** `'Additional Revenue'` | Year | Product | Value | | ---- | ------- | ----- | | 2025 | A | 95 | | 2026 | B | -56 | | 2027 | A | 107 | | 2027 | B | 5 | **Formula:** `TRUE('Revenue'+'Additional Revenue')` | Year | TRUE Result | | ---- | ----------- | | 2025 | 1 | | 2026 | 1 | | 2027 | 1 | The addition rolls up both nodes to their common dimensions (Year only), and TRUE returns 1 for each defined year. ### Undefined values remain undefined TRUE only produces `1` for defined values. Rows where the input is undefined remain undefined in the result. **Input node:** `'A'` | Year | Revenue | | ---- | ------- | | 2025 | 59 | | 2026 | | | 2027 | 157 | **Formula:** `TRUE('A')` | Year | TRUE Result | | ---- | ----------- | | 2025 | 1 | | 2026 | | | 2027 | 1 | Year 2026 has no defined value, so it does not appear in the result. ## Related | Function | When to use instead | | ----------------- | --------------------------------------------------------------------------------------------------- | | [FALSE](/false/) | When you need `0` for every defined value instead of `1`. | | [IS\_NA](/is-na/) | When you need to detect undefined values rather than marking already defined intersections as true. | --- # Tutorials - Modelle URL: https://docs.valsight.ai/tutorials-modelle/ Description: In diesem Video erfährst du, wie du in Valsight ein neues Projekt erstellst. Du lernst, einen Projektnamen, einen Business Key und den passenden Zeithorizont… Diese Tutorials zeigen, wie Sie ein neues Projekt in Valsight anlegen und Projekte über Szenario-Exporte miteinander verbinden. ## Ein neues Projekt anlegen Video: [Ein neues Projekt anlegen](https://youtu.be/q5uCYizoo9A) In diesem Video erfährst du, wie du in Valsight ein neues Projekt erstellst. Du lernst, einen Projektnamen, einen Business Key und den passenden Zeithorizont (Jahre, Quartale, Monate) zu wählen. Nach dem Erstellen kannst du das Projekt über die Übersicht öffnen und auf deine Arbeitsbereiche zugreifen. > **Wochen stehen beim Anlegen nicht zur Auswahl.** Die Liste **Horizon Period** enthält im Anlegen-Dialog immer nur Year, Quarter und Month, auch in der deutschen Oberfläche und auch in englischer Schreibweise. Ein Projekt auf ISO-Wochen legst du zunächst normal an und stellst es danach in den [Projekteinstellungen](/project-settings/) unter **Jahre unterteilen in** um. [Mehr Details](/creating-a-project/) ## Projekte verbinden mit Szenario Exporten Video: [Projekte verbinden mit Szenario Exporten](https://www.youtube.com/watch?v=Y2AZsEEdMWA) In diesem Tutorial zeigen wir dir, wie du Exporte für andere Projekte freigibst, Exportszenarien in Zielprojekte importierst und simulierte Knoten in neuen Projekten nutzen kannst. Erfahre außerdem, wie du Exporte aktualisierst und deine Datenquellen immer auf dem neuesten Stand hältst. [Mehr Details](/importing-scenarios/) und [Exporte freigeben](/sharing-exports/) --- # UNION URL: https://docs.valsight.ai/union/ Description: The UNION function combines the result sets of two or more input nodes into one output. All inputs must have the same levels and must not have overlapping rows. **Category:** [Assumptions & result sets](/assumptions-result-sets/) ## Overview The **UNION** function **combines the result sets of two or more input nodes** into one output. Use this function when you want to append non-overlapping result slices from nodes that share the same dimensional structure. UNION is a stricter version of [ADDITION (+)](/addition/) and can serve as an extra guardrail because the inputs are required to have the same levels. ## Syntax `UNION('Node1', 'Node2' [, 'Node3', ...])` **Example usage:** `UNION('Salary Q1', 'Salary Q2')` ## Parameters | Parameter | Description | Type | Required | | -------------------- | ----------------------------------------------- | -------------- | -------- | | **Node1** | First input node to combine | Node reference | Yes | | **Node2** | Second input node to combine | Node reference | Yes | | **Additional nodes** | Any number of additional input nodes to combine | Node reference | No | ## Output shape | Aspect | Behavior | | -------------- | -------------------------------------------------------------------------- | | Dimensionality | Same as all inputs (they must all have the same levels). | | Level values | Union of all level values from all inputs. | | Row count | Sum of all input row counts. No aggregation or deduplication is performed. | ## Watch out * All inputs must have the **same levels**. * Inputs must **not have overlapping rows**. If any row key appears in more than one input, the calculation fails at runtime. * The same node **cannot appear more than once** in the parameter list. * All inputs must have the **same unit**. ## Examples ### Appending non-overlapping slices This example shows UNION combining two disjoint salary slices with the same level structure. Because the rows do not overlap, the result appends both slices into one output. **Input node:** `'Node1'` | Year | Employee | Salary | | ---- | -------- | ------ | | 2025 | E1 | 50,000 | | 2025 | E2 | 60,000 | **Input node:** `'Node2'` | Year | Employee | Salary | | ---- | -------- | ------ | | 2026 | E1 | 55,000 | | 2026 | E2 | 66,000 | **Formula:** `UNION('Node1', 'Node2')` | Year | Employee | UNION Result | | ---- | -------- | ------------ | | 2025 | E1 | 50,000 | | 2025 | E2 | 60,000 | | 2026 | E1 | 55,000 | | 2026 | E2 | 66,000 | ## Related | Function | When to use instead | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | [ADDITION (+)](/addition/) | When overlap is allowed or expected, or when the inputs do not need UNION's same-level and no-overlap constraints. | | [ROLLUP](/rollup/) | When you need to change granularity or aggregate a node to different levels instead of combining disjoint result slices. | --- # Units URL: https://docs.valsight.ai/units/ Description: Units in Valsight are display labels assigned to model nodes, such as EUR, km, or compound units like EUR / km. They help users interpret values in context an… Units in Valsight are display labels assigned to model nodes, such as `EUR`, `km`, or compound units like `EUR / km`. They help users interpret values in context. Units are not purely cosmetic. Two things depend on them: * **Growth drivers in a roll-forward.** In [ROLLFORWARD](/rollforward/) and [ROLLFORWARD\_ADVANCED](/rollforward-advanced/), a driver node whose unit is a percentage is applied as growth rather than as an addition. Put the wrong unit on a growth driver and you silently get an absolute addition instead. * **Model validation.** A node whose assigned unit disagrees with the unit its formula calculates is reported as a warning, "Calculated unit mismatch: you specified X but the calculation returns Y". Adding or subtracting two operands that carry different units fails outright. > **A percentage unit does not make changes to the node relative** > > Whether a change entered in the Scenario Manager is absolute or relative is a property of the line-item, not of the node's unit. The two are unrelated. See [Creating a Line-Item](/creating-a-line-item/). ## Assigning units to a node In the Node Editor (right-hand panel of the Model Editor), open the **Units** section and select a unit from the list. ![Model Editor\_Units dropdown highlight.png](./images/6877806633.png) For nodes that express a ratio, select a compound unit by combining two labels (e.g. `EUR / km`). ![Model Editor\_Compound Units highlight.png](./images/6878199827.png) If the unit you need is not listed, contact your project admin. The available unit list is project-wide and managed in Admin Settings > Units. A model can also carry a **Default Unit**, set in step 1 of its Edit Model dialog, which is given to every node created in that model. See [Creating and Configuring Models](/creating-and-configuring-models/). ![image-20260401-174339.png](./images/6859358227.png) ## Related * [Configure Units](/configure-units/) --- # Update / Upgrade the installation URL: https://docs.valsight.ai/update-upgrade-the-installation/ Description: Follow these simple steps to keep the software up-to-date. Follow these simple steps to keep the software up-to-date. *Important: Always create a database backup before an application update. Updates can include database migrations, and although migrations are tested to the best of our knowledge, they always carry the risk of a failing migration that leaves the database in an inconsistent state.* ## Pre-upgrade 1. Download the installation zip file from the link provided by your Valsight support representative 2. Stop the service 3. Create a backup of the database and the application directory (See [Backup & Recovery](/backup-recovery/)) ## Upgrade 1. Unzip the installation file of the new version in the same directory, overwriting existing files. Do not overwrite your runtime files: 1. the configuration directory `conf/` (including `conf/config.yml`) 2. the license file `license.pem` 3. the database files `db/*.db`, if you run the integrated database 2. Windows only: adapt the version number in `/windowsservice/windowsservice.xml`. ## Post-upgrade 1. Start the application. 1. On the first start of a new version, the database is upgraded & migrated automatically - it may take a little longer than a regular start. 2. Optional: Remove old rest-service-(old-version).war files from the */lib/* directory. ## Troubleshooting In case the application does not start after the upgrade double check the following: * Windows only: Have you updated the version number in the XML File * Does the log contain a message like the following? ``` ERROR o.s.boot.SpringApplication - Application startup failed liquibase.exception.LockException: Could not acquire change log lock. Currently locked by ... ``` In this case, a failed startup has locked the database. Double check that no application (java) process is running anymore and then run the SQL command from [Resetting the Database CHANGELOGLOCK](/resetting-the-database-changeloglock/). --- # Updating level values via data source upload URL: https://docs.valsight.ai/updating-level-values-via-data-source-upload/ Description: To use this feature the dimensions and level values to be updated need to already exist. Create them first in the dimension management. You can add and delete level values from your dimensionality via an excel data source upload. *Important: To use this feature the dimension to be updated needs to already exist. Create it first in the [dimension management](/creating-maintaining-dimensions/). The level values themselves do not have to exist yet, since adding the ones that are missing is what the second option below does.* Updating the level values of your dimensionality has to be done separately for each dimension. ## How to update your dimensionality via Excel With this feature, Valsight allows its users to add and remove [level values](/creating-maintaining-dimensions/) from its [dimensionality](/creating-maintaining-dimensions/) by uploading an excel file as a data source. By [uploading a new data source](/data-upload-import-export-overview/), Valsight automatically identifies the dimensions listed in this data source. Via the level values and measures validation button, users can check whether there have been any errors or unmatched level values in their data source. In the "Dimension Management" - tab it is possible to update each dimension separately based on the dimensionality in the selected sheet. ![image2022-11-22\_16-47-0.png](./images/5094207317.png) After selecting a dimension to be updated and a sheet/table the dimension should be updated from, there can be three cases of updates: 1. Level values have been **added** to the dimensionality. 2. Level values have been **removed** from the dimensionality. 3. Level values have been **added and removed** from the dimensionality. To get an overview over these three cases, per default, two tables will be visible. The first one is called "Unmatched Level Values" and lists all level values that could be added to the dimensionality. The second one is called "Removed Level Values" and lists all level values that can be removed from the dimensionality. There are use cases for all three cases and therefore, the user has the option to either **(1)** **replace the current dimensionality with the new dimensionality** from the data source or **(2) only add the unmatched level values to the current dimensionality**. The **(1) first option** "overrides" the current dimensionality with the dimensionality from the data source which takes the unmatched level values as well as the removed level values into account. The **(2) second option** adds the unmatched level values from the data source to the existing dimensionality and ignores the removed level values. > **The second option only looks at the lowest level.** It compares the lowest-level column of your data source against the dimension and adds the values it does not find there. Two consequences follow: > > * A row whose lowest-level value already exists is skipped in full, so **changing the parent of an existing value has no effect** in this mode, even though the row looks different from what the dimension holds. > * A value that appears only on an upper level is never added, because nothing on the lowest level is new. > > Use the first option when the hierarchy itself has to change. It is the only one that applies the whole structure from the data source. ![tempsnip.png2.png](./images/5094207156.png) ## Shortcut To simplify the process of updating multiple dimensions quick after another, a shortcut has been implemented. To take this shortcut, simply select the dimension to be updated in the dropdown menu. The row in which you select the dimension defines the sheet taken as a source. This shortcut saves the user time as it skips the table with other errors found and immediately shows you the overview of unmatched or removed level values. ![tempsnip.png 1.png](./images/5094207119.png) ## Limitations There are some limitations to keep in mind when using this feature. * It is not possible to add any dimensions nor levels to the dimensionality * It is required to always provide the full dimensionality * It is not possible to update levels with linked levels * Updates can only be done one dimension at a time --- # User Authentication URL: https://docs.valsight.ai/user-authentication/ Description: Valsight can delegate the user authentication to your enterprise authentication service. Our recommended integration method is Single-Sign-On with OpenIDConn… Valsight can delegate the user authentication to your enterprise authentication service. Our recommended integration method is Single-Sign-On with OpenIDConnect. You may implement two factor authentication in your authentication service. --- # User Settings URL: https://docs.valsight.ai/user-settings/ Description: Personal account settings in Valsight: password, language, and keyboard shortcuts. Personal account settings in Valsight: how to manage your password, change your language, and work faster with keyboard shortcuts. ## Password ### Reset password It is not possible to reset your password via Valsight. To reset your password, you need to contact your project administrator or the Valsight support: or +49 30 46799042 ### Change password You can change your password by clicking on your account's initials in the bottom left corner of the app. This will open the following tab where you can enter a new password. ![image-20240122-143228.png](./images/5346951232.png) > This only applies to Valsight Users that login with Valsight Usernames + Password. If your are using your companies Identity Provider (Single-Sign-On), change your password there. ## Language settings ### Global language settings This setting is used to set the default language settings for the entire instance and each user on login. It is best to use this when setting up the Valsight instance to match your internal communication language. To set the default language for all users of your instance, navigate to the Project Settings, scroll to the featureFlags.userLanguage setting and select the language you require. ![Frame 2 (2).png](./images/5539102733.png) ### User language settings You can change the language specifically for your account through the User Preferences. Click the User icon at the bottom of the navigation bar. Then navigate to the language settings at the bottom and change it to the language you prefer. ![Frame 3 (1).png](./images/5538840607.png) > Please note that changing the language settings also effects the number format. *(i.e. EN: 100,000.10 DE: 100.000,10)* ## Keyboard shortcuts A list of all keyboard shortcuts in Valsight. | Place | Action | Shortcut | Note | | -------------------- | ------------------------------------------------- | --------------------------------------------------------------------------- | ------------------- | | Model Editor | Search Nodes | CTRL + F (⌘ + F on Mac) | | | Model Editor | Copy/Paste Nodes | CTRL + C/V (⌘ + C/V on Mac) | | | Model Editor | Add Node to selection | CTRL + Click (⌘ + Click on Mac) | | | Model Editor | Select all Nodes | CTRL + A (⌘ + A on Mac) | | | Simulation Workspace | Search Sheets | CTRL + F (⌘ + F on Mac) | | | Simulation Workspace | Jump between last used Sheet and Scenario Manager | CTRL + J (⌘ + J on Mac) | Deprecated in 5.1.0 | | Simulation Workspace | Switch Sheets in the Tabbar | CTRL + arrow left/right (⌘ + arrow left/right on Mac), hit Enter to confirm | | | Dimension Management | Open Dimension search | CTRL + F (⌘ + F on Mac) | | --- # Using Project Variables in Node Formulas URL: https://docs.valsight.ai/using-project-variables-in-node-formulas/ Description: In the node formula editor, type $ to open the variable picker and select from the list of available variables. In the node formula editor, type `$` to open the variable picker and select from the list of available variables. ## As dynamic level values Variables are commonly used as **level values in dimension parameters**, especially for the time dimension. Instead of hardcoding a specific year, you can reference a variable that updates automatically. **Example:** `FILTER('Revenue', "Year", "$FC_End")` This pattern works in any function that accepts level values, such as [FILTER](/filter/) that reference dimension members. ## In DATA function parameters Variables can be embedded anywhere within a DATA parameter string to dynamically reference data sources or tables: `DATA("Datasource_$Variable", "TableName", "MeasureName")` `DATA("DataSourceName", "$TableName", "MeasureName")` This allows scenarios to switch between different data sources or tables without changing the formula. See the [DATA](/data/) function page for a full overview of placement patterns. ## Related * [Nodes](/nodes/) * [Working with different Model Baselines](/working-with-different-model-baselines/) * [Define Calculations for a Node](/define-calculations-for-a-node/) * [Project Variables](/project-variables/) --- # AI Assistant URL: https://docs.valsight.ai/using-the-ai-assistant/ Description: Use the Valsight AI Assistant to understand models faster, get oriented in complex projects, and create documentation more easily. Use the Valsight AI Assistant to **understand models** faster, **get oriented** in complex projects, and **create documentation** more easily. It is designed in a **read-only** mode, to support understanding and orientation, not to modify models or perform actions for you. **Editing is coming soon.** The Assistant is read-only today, but the ability to have it build and change models for you is in development and will arrive in a future release. If you want an AI client to work with your models now, see the [Valsight MCP integration](/valsight-mcp-server/). ## Interacting with the AI Assistant Video: [AI Assistant](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6844022807_AI-Assistant.mp4) ## What you can use it for ### Onboarding and guidance Use the assistant when you are new to a model or project and want a faster starting point. **It can help you:** * understand model structure and node types * get oriented in unfamiliar projects * identify where to start when reviewing an existing model * understand Valsight concepts in model context ### Explainability and troubleshooting Use the assistant when you want to better understand how a model works or investigate something unexpected. **It can help you:** * explain how nodes are calculated * identify relationships between drivers, dimensions, and submodels * understand why certain behaviors appear in the model * narrow down where to look when model behavior seems unclear ### Modeling and documentation Use the assistant when you want help phrasing, summarizing, or documenting model logic. **It can help you:** * draft descriptions for nodes or model sections * summarize model relationships for handover or review * explain modeling logic in simpler language * suggest how to document technical structures more clearly ## What the AI uses to answer questions The AI Assistant builds its answers from non-numeric, descriptive information available in Valsight, including: * model and submodel structure, node types, and relationships * annotations such as sticky notes, frames, and descriptions * dimensions and levels * formulas and syntax * data table names, column names, and metadata Model changes are reflected immediately in the AI context. ## What the AI cannot access or do To preserve data privacy and correctness, the AI Assistant does not have access to: * numeric values or calculated results * historical data values * external systems outside Valsight * personal credentials * projects beyond your permissions The AI Assistant also cannot: * modify models, data, or scenarios * perform actions in Valsight on your behalf * replace business review or modeling judgment ## How to ask better questions You will usually get better answers when your question is specific and includes the context you care about. **Instead of:** Explain this node. **Try:** Explain how the node `'XXX'` is calculated and highlight the most important drivers. **Instead of:** Help me document this model. **Try:** Draft a short model overview I can use for internal handover. **Instead of:** Explain this project. **Try:** Explain how the models in this project are connected and where I should start reviewing. ## Important to keep in mind AI-generated responses are informational and should always be validated against your business knowledge and modeling intent. The assistant works best when your model contains clear names, descriptions, and annotations. ## Related * [AI Assistant](/ai-assistant/): overview * [FAQ: AI Assistant](/frequently-asked-questions-valsight-ai-assistant/): common questions and troubleshooting - [Valsight MCP integration](/valsight-mcp-server/): connect an external AI client instead of chatting in the app --- # Using the Presentation Mode URL: https://docs.valsight.ai/using-the-presentation-mode/ Description: Create a static snapshot of a workspace and present it view-only, or keep it as a record of where the plan stood. A workspace is good in a group discussion, because assumptions can be adjusted on the spot. Sometimes you want the opposite: something formal and fixed that will not change under you while you present it. That is what presentation mode is for. ## What it is Presentation mode shows a **snapshot** of a workspace: a static, view-only copy taken at a moment you choose. Charts and data cannot be edited in it, and it opens in its own tab. A snapshot is fully self-contained. It keeps no connection to the workspace it came from, nor to the data, levels, hierarchies or assumptions behind it. ## When to use it * You are presenting to a steering committee or a board and want a fixed version that cannot be altered mid-discussion. * You want to hand someone a read-only view without giving them the workspace. * You want to record where the plan stood at a point in time, as documentation of your work. ## Configuration ### Create a snapshot 1. Click the downward arrow in the top bar. 2. Click **Create Presentation**. ![The Create Presentation option in the workspace menu](./images/5094231048.png) A notification confirms that the snapshot is being created. For a very large workspace this can take a moment. ### Open and present it 1. Go to the presentation space through the navigation bar. The menu lists your snapshots along with which workspace each came from, who created it and when. ![The presentation space listing a snapshot with its workspace, author and date](./images/5094231044.png) 2. Click the name of the snapshot. It opens in a separate tab. 3. Click **Presentation Mode**. ![The Presentation Mode button on an opened snapshot](./images/5094217135.png) Once you are in, the arrows at the top of the page move through the presentation, and the button on the left opens the Scenario Manager if you want to show it. **Print** in the top right corner produces a printable version, which you can send to paper or to PDF. ### Set what a sheet looks like in a presentation Each sheet carries its own presentation settings, in the **Sheet and Group Configuration** dialog reached from the sheet tab bar. Under **Presentation Settings** the dialog notes that "These settings apply to this sheet when it is displayed in presentation mode", and offers: | Setting | What it does | | ------------------------------ | --------------------------------------------------------------------- | | **Sheet Title** | A title used for this sheet in presentations instead of its tab name. | | **Sheet Subtitle** | A subtitle shown beneath that title. | | **Exclude from presentations** | Leaves the sheet out of every snapshot of this workspace. | **Exclude from presentations** is the only way to control which sheets a snapshot contains. Set it on the working sheets you do not want an audience to see, before you create the snapshot. ## Good to know * **It is truly view-only.** Charts and data cannot be edited in presentation mode. That is the point of it, not a limitation to work around. * **A snapshot never updates.** Because it is self-contained, your model can advance, your data can be reloaded and your assumptions can get new values, and the snapshot stays exactly as it was. This is what makes snapshots usable as an archive. * **Four tile types cannot be drawn in a presentation.** Sliders, [Split Sliders](/split-sliders/), model [Tree](/model-tree/) charts and [Input Tables](/input-tables/) are all unrenderable there. The tile is still part of the snapshot and still occupies its place on the sheet, it just shows the message "This chart type is not supported in presentation mode." instead of the chart. If that placeholder would be distracting, move those tiles onto a sheet you exclude from presentations. * **A large workspace takes a moment to snapshot.** Give it time rather than clicking again. ## Related * [Chart Types](/chart-types/): the tiles a worksheet can hold before you present it. * [Split Sliders](/split-sliders/): a tile that stays behind in the workspace. * [Creating Charts](/creating-charts/): building the sheet you present from. --- # Using Workflows (For Contributors) URL: https://docs.valsight.ai/using-workflows-for-contributors/ Description: The guide for individual contributors importing and submitting workflow steps *The guide for individual contributors importing and submitting workflow steps* ## What are workflows & shared scenarios? A Workflow is a process that allows multiple users and departments to collaborate on a larger project. It works with shared Scenarios and defines the logic of when, where, and with whom Scenarios are shared. In Valsight, you can create a Scenario by navigating to your workspace and clicking on '[Scenario Manager](/scenario-manager/)' (1). In the case of the Workflows, the Scenarios for this Workflow will be created automatically. You can then make assumptions and measures for your department. For more information on how to create your first Assumptions, please refer to our Assumptions documentation\*\*.\*\* ## Viewing and importing workflow steps You can view each Workflow step and your submissions by clicking on the Workflow icon (2). To start work on your Workflow step and associated Scenarios, it may be necessary to use a Scenario from another user or department as input. For example, base assumptions that you can build on and simulate. To see all the previous steps you need to start building your Scenario, navigate to 'Import Previous Steps'. If you are part of multiple Workflows, you may need to select the desired Workflow and step first. If you are unsure which is correct, contact the Admin or creator of the Workflow to check. ![image2024-7-12\_10-58-15.png](./images/5617549329.png) The list tells you which steps you need to import and their status. The last column, 'Changes', indicates whether there are any changes available for you to import. There may be changes after you have imported a previous version. In this case, there will be a difference between your current version and the available version. You will be notified when new changes are available by the orange workflow icon (xxx) To import any new changes in the scenarios, select one or more scenarios and click 'Import'. ![image2024-7-12\_10-22-1.png](./images/5617418265.png) You will now see the imported Scenarios in your assumptions: ![image2024-7-12\_11-4-28.png](./images/5617647646.png) The assumptions are taken into account when you create your own. When you look at charts after you have made changes, previous users' assumptions will be included. You do not need to do anything. To see only your own assumptions, you can uncheck the shared Scenarios. ## Sharing your step Once you have finalized your Scenario by creating assumptions and line items, and filled in all the necessary tables and figures, you can hand your Scenarios on for potential review. To do this, navigate back to the Workflow icon and click on 'Share Workflow Steps'. If necessary, select the required Workflow and step again. You will see a list of all your Scenarios included in that Workflow. ![image2024-7-12\_11-17-18.png](./images/5617254475.png) Select the ones that are ready. The dialogue has two buttons: * **Share & Promote:** shares the Scenario and moves it on to indicate that it is final and ready for review. This will change the status from 'Open' to another status depending on your Workflow settings. * **Share:** shares the Scenario but does not change the status. This is useful if you want to share or save a Scenario that is still in progress. Once your Scenarios have been shared, you will be able to see the status changes made by potential reviewers. > **Do not rename a shared Scenario.** Workflow Scenarios are linked to the Workflow by their name. Renaming one in the Scenario Manager unlinks it from the Workflow, and naming another Scenario exactly like a Workflow Scenario links that one in instead. Valsight asks you to confirm before saving such a rename. --- # Validate Dimensions URL: https://docs.valsight.ai/validate-dimensions/ Description: You can use the "Validate Dimensions" functionality to check that all level values are present in the Dimension table. You can use the "Validate Dimensions" functionality to check that all level values are present in the Dimension table. The check reports the level values it could not match, and nothing more: it does not correct them for you. Production-ready models should have no unmatched level values, so correct them in your base data or in your Dimension tables as soon as possible. Unmatched values otherwise often lead to unexpected results. A few tips: * Look for leading and trailing spaces. A trailing space in Excel can be very easily overlooked, but the system treats "ABC" different from "ABC ". * If your file contains only data tables, e.g. no =DIM identifier, you can upload it to a new data source and validate the Dimensions there without affecting your primary or production data source. ![2018-07-23 09-12-19.png](./images/5094192827.png) --- # Validation Nodes URL: https://docs.valsight.ai/validation-nodes/ Description: Validation nodes let you define custom conditions inside your model that flag deviations during validation checks. Validation nodes let you define **custom conditions** inside your model that flag **deviations** during validation checks. ## When to use it * When formulas can produce results that are technically valid but logically wrong (e.g. negative volumes, margins exceeding 100%) * When you want automated checks for business rules that model validation cannot catch ## How it works Validation nodes work like regular nodes but serve a specific purpose: their result is interpreted as a pass/fail signal during validation. * A result of **0** (or all zeros): the check **passes** (no issues). * A result **other than 0**: the check **fails** (the non-zero value indicates the deviation). You can use any formula logic to express the condition. Common patterns use [IF](/if/), [MIN](/min/), [MAX](/max/) and [Comparisons & boolean operators](/comparisons-boolean-operators/) ## Adding a validation node 1. Open your model in the **Model Editor**. 2. Click **Add Node** in the action bar. 3. Select **Validation Node** from the node type menu. 4. Name the node and define its formula. ![image-20260402-092417.png](./images/6861455367.png) ## Common patterns ### Check that a value is never negative | Node | Formula | Logic | | ------------------ | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | **PositiveVolume** | `IF('Volume' >= 0, 0, 'Volume')` | Returns **0** when volume is non-negative (passes). Returns the actual volume when negative (fails and shows the deviation). | | **PositiveVolume** | `MIN(0, 'Volume')` | Equivalent shorthand. Returns **0** when volume is positive, returns the negative value otherwise. | ### Ensure a value stays within a range Use `IF` with combined conditions to check a lower and upper bound at the same time. | Node | Formula | Logic | | ------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | **DiscountInRange** | `IF('Discount Rate' >= 0 AND 'Discount Rate' <= 0.5, 0, 'Discount Rate')` | Returns **0** when the discount rate is between 0% and 50% (passes). Returns the actual value when outside that range (fails). | ### Flag values that should never be zero Use `IF` to detect zeros where a positive value is expected. | Node | Formula | Logic | | -------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------- | | **NonZeroHeadcount** | `IF('Headcount' != 0, 0, 1)` | Returns **0** where headcount is non-zero (passes). Returns **1** where headcount is zero (fails). | ### Combine multiple conditions Use `AND`, `OR` to check several rules in one validation node. | Node | Formula | Logic | | ---------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | | **RevenueConsistency** | `IF('Revenue' > 0 AND 'Volume' > 0, 0, 1)` | Returns **0** when both revenue and volume are positive (passes). Returns **1** when either is zero or negative (fails). | ## Running validation node checks You can evaluate validation nodes in two ways: **From the Model Editor:** Click the **Validation Node Checkup** button in the header bar. This runs all validation nodes against the current model state. ![image-20260402-092712.png](./images/6862831642.png) **From a Workspace:** Validation nodes are also evaluated automatically during [Workspace Validation](/workspace-validation/), which checks conditions across all active scenarios. ## Limitations * Validation nodes only check results. They do not change calculations or outputs of other nodes. * The pass/fail signal is based on the numeric result: zero passes, non-zero fails. Design your formula accordingly. * Validation nodes are evaluated per intersection (every combination of dimension values), so a single validation node can flag multiple issues at different intersections. * **Only the first 50 deviations per validation node are listed.** The results dialog says so, and the number is an instance-wide setting an administrator can change. A node showing exactly 50 rows has almost certainly hit the cap, so treat that as a sample rather than a count. * If the validation node's query cannot run at all, for example because you lack access to some of the data it reads, the result is an error rather than a list of deviations. An empty result is not always a pass. ## FAQ **Do validation nodes affect model results?** No. They only check results. They do not influence the calculations of other nodes. **What is the difference between model validation and validation node checks?** Model validation checks syntax and structure. Validation node checks evaluate whether your custom conditions are met at the result level. **Can I use validation nodes without workspace validation?** Yes. You can run the Validation Node Checkup directly from the Model Editor at any time. ## Related * [Model Validation](/model-validation/): syntax and structure checks * [Workspace Validation](/workspace-validation/): evaluates validation nodes across scenarios * [Expected Levels](/expected-levels/): pre-define the shape of empty nodes used as blueprints * [IF](/if/), [MIN](/min/), [MAX](/max/), [Comparisons & boolean operators](/comparisons-boolean-operators/): functions and operators commonly used in validation node formulas --- # Validations URL: https://docs.valsight.ai/validations/ Description: Validations check that your data, models, and workspaces are correctly configured, compatible, and working as intended. Validations check that your **data**, **models**, and **workspaces** are correctly configured, compatible, and working as intended. ## What you can validate | Area | What is checked | Where to find it | | --------------------- | ---------------------------------------------------------------------------------------------------- | ------------------- | | **Data & Dimensions** | Uploaded data complies with defined dimensions, contains no wrong values, and is correctly formatted | Data Source page | | **Models** | Node formulas follow correct syntax and are compatible with connected data | Model Editor header | | **Workspaces** | Scenarios and model logic function correctly together | Workspace header | ## Start here if you want to: | If you | Go to | | ------------------------------------------------------ | ---------------------------------------------------------- | | Check uploaded data against your dimensions | [Data & Dimension Validation](/data-dimension-validation/) | | Verify model syntax and compatibility after a change | [Model Validation](/model-validation/) | | Check that workspace scenarios produce correct results | [Workspace Validation](/workspace-validation/) | | Add custom checks to your model logic | [Validation Nodes](/validation-nodes/) | | Pre-define the expected shape of empty nodes | [Expected Levels](/expected-levels/) | ## Who this section is for * Users uploading or managing data who want to verify correctness before connecting it to models * Modelers building or maintaining models who need to check formula validity * Teams reviewing workspaces or investigating unexpected results across scenarios --- # Valsight API Client URL: https://docs.valsight.ai/valsight-api-client/ Description: To download the client, contact the Valsight Support at support@valsight.com . To download the client, contact the Valsight Support at . Valsight ships a tool to simplify programming against the API. It handles cookie authentication and provides useful methods to access objects as well as many default java & groovy methods to simplify the handling of JSON responses. Its only requirement is a Java runtime of version 21 or later. You can also use any other tool to access the REST based API. ## Running the Valsight client ``` java -jar valsight-client-launcher-x.x.jar (-s | --serverless) ([-u -p ] | [-u -k ]) ``` ## Example script ```groovy import groovy.json.JsonOutput import org.apache.commons.cli.CommandLine import org.apache.commons.cli.CommandLineParser import org.apache.commons.cli.DefaultParser import org.apache.commons.cli.Options // static imports are required for autocompletion import static com.valsight.rest.ScriptDelegate.client import static com.valsight.rest.ScriptDelegate.log // Variables/environment passed to the script: // // ValsightRESTClient client: a connected/logged in ValsightRESTClient instance (unless --serverless mode is specified) // String[] args: the list of all script arguments // Logger log: a logger with the name of the script // Example: parsing command line arguments // The script is passed all remaining command line arguments after the script launcher // has processed its arguments (e.g. server url / username) // You can use any mechanism to parse the args, commons-cli is in the classpath and is recommended log.info "All args: ${args}" Options options = new Options() options.addOption('project', 'project-key', true, '') CommandLineParser parser = new DefaultParser() CommandLine cmd = parser.parse(options, args) log.info "Options/flags: ${cmd.options.collectEntries { [it.opt, it.value] }} " log.info "positional arguments: ${cmd.args}" // Example: using the ValsightRESTClient object List projects = client.findAllProjectSpaces() String projectFilter = cmd.getOptionValue('project') if (projectFilter != null) { projects = projects.findAll { it.businessKey.equals(projectFilter) } } else { log.error "Please specify a project." System.exit(1) } Long projectID = projects[0]['id'] String projectName = projects[0]['name'] String projectKey = projects[0]['businessKey'] log.info "Working on Project $projectName (Key: $projectKey, ID: $projectID)" // For more convenient method calls on client, you may use the standard Groovy .with {} log.info "The following models and nodes are found in the project" client.with { getObjects('models',['project':projectID ]).each { model -> log.info model['name'] log.info "Status: " log.info client.getPath("models/${model['id']}/validate").isEmpty() ? ' Valid' : " Invalid: ${client.getPath("models/${model['id']}/validate").toString()}" model['nodes'].each { nodeId -> log.info " " + getObject('nodes', nodeId)['name'] } } log.info "The following datasources are available" getObjects('externalDataSources',['project':projectID ]).each { ds -> log.info " ${ds['name']} (${ds['id']})" log.info "Status: " + client.getPath("externalDataSources/${ds['id']}/status").toString() } } ``` --- # Valsight CERT & ISO URL: https://docs.valsight.ai/valsight-cert-iso/ Description: Get in Touch with the Valsight Computer Emergency Response Team (CERT) Report a security issue to Valsight's Computer Emergency Response Team (CERT) or Information Security Officer (ISO). This page lists the contact channels and the response times you can expect. ## Get in touch with the Valsight Computer Emergency Response Team (CERT) Feel free to contact us in any security-related question on the Valsight product or infrastructure, and particularly if you want to report a potential security issue. Please bear in mind that only emails composed in English or German can be considered, and encrypted communication is preferred. You can expect us to respond till the next business day in Germany (City: Berlin). Email: Hotline: +493046799042 ## Get in touch with the Valsight Information Security Officer (ISO) You can contact the Valsight ISO in German or English at . --- # Valsight Enterprise Cloud Hosting Options - Comparison URL: https://docs.valsight.ai/valsight-enterprise-cloud-hosting-options-comparison/ Description: Valsight Enterprise Cloud Hosting Options - Comparison

We host

You Host

Remarks

Compute & Storage Provider

Open Telekom Cloud

Azure

AWS

Fully Self Managed (On Premise)

Valsight Managed in Your Cloud

(AWS or Azure)

ISO27001 Certification

Your compliance framework applies.

TISAX

Depends on Location

Location

Biere, Germany

Frankfurt, Germany

Frankfurt, Germany

Your Choice

Your Choice

Encryption at Rest

CMK

CMK

CMK

Your Choice & Responsibility

CMK

CMK = Customer Managed Key, created and stored in Cloud-Providers KMS.

Encryption in transit

Your Choice & Responsibility

Private Routing

Possible everywhere through direct VPN connect. For fully-self managed a “no internet at all” setup is possible.

IP-Level Filtering

Valsight Staff Access

Yes

Yes

Yes

No

Yes

Valsight staff can access your data, e.g. to help in support cases.

Costs for Storage & Compute included in Valsight SaaS Subscription

Off-Site DR

Your responsibility

Optional

--- # Valsight MCP integration URL: https://docs.valsight.ai/valsight-mcp-server/ Description: The Valsight MCP integration lets external AI agents connect to Valsight and work with your models over a standard, permission-scoped interface. The **Valsight MCP integration** exposes your Valsight models to external AI agents over the **Model Context Protocol (MCP)**, an open standard for connecting AI clients to tools and data. It is the external-client counterpart to the [in-app Assistant](/using-the-ai-assistant/): instead of chatting inside Valsight, you connect your own AI client — such as Claude — through the **MCP server**, and it both **explores and changes** your models on your behalf, always inside a session whose scope and permissions you control. *Important: The Valsight MCP integration is a premium feature, available from Valsight 7.3.0.* * **Free through 31 December 2026** — included for all customers at no additional cost. Connect your own AI client, work with your real models, and see what it adds. * **A paid add-on from January 2027.** * **Off by default** — it is opted into per instance and needs some setup. To switch it on, or to talk through whether it fits your team, write to **** or contact your Customer Success representative. ## What it is The MCP server is a connection layer, not a screen inside Valsight. An external AI client connects to it, authenticates, and receives a set of **tools** it can call to work in a project on your behalf — reading model structure and metadata, and, when the session allows it, making changes. Every connection runs as a **session** that is scoped and permissioned up front (see [Session scope and permissions](#session-scope-and-permissions)). Nothing the agent does escapes that session's boundaries. ## What you can do with it A connected agent can, within the session's scope and permissions: * **Explore models** — search across models, workspaces, data sources, and dimensions; inspect nodes, levels, and their usage; read formulas, functions, and entity definitions. * **Read data** — fetch calculation results, line-item value tables, and dimension values (subject to the session's data-access setting). * **Build and edit models** — create, update, duplicate, and delete entities; manage line-item levels; add dimension rows. * **Work with charts** — create and update charts and their display configuration, including chart and perspective images. * **Manage scenarios and workspaces** — select scenarios/workspaces, share and unshare scenarios, and export scenario versions and template nodes. * **Handle data sources and ETL** — upload data, map data-source columns, import tables, and build and run ETL pipelines. * **Run workflows** — list, configure, and manage multi-step workflows. * **Analyze** — validate workspaces, models, and data sources, and inspect calculation performance. * **Manage access** — explain access-rights breakdowns and grant or revoke access (only when the session is permitted to modify access rights). * **Use the knowledge base** — search and read Valsight product documentation, and list and read guided skills. * **Move data in and out** — download entities as Excel, and upload files into the session. ## Session scope and permissions Each session is bounded on five independent axes, chosen when the client connects. This is the core safeguard: a session can only ever do what its axes allow. | Axis | Options | Default | What it controls | | ------------------------- | --------------------------------- | -------- | ---------------------------------------------------------------------------------------------------- | | **Project scope** | one or more projects, or unscoped | unscoped | Which project space(s) the agent may touch. Every entity is checked against this scope. | | **Access level** | `read_only`, `write` | `write` | Whether mutating tools are allowed at all. In `read_only`, change actions are refused. | | **Data access** | `full`, `restricted` | `full` | Whether numeric values (calculation results, line-item values) are exposed. `restricted` hides them. | | **Project deletion** | allowed / blocked | allowed | Whether whole project spaces may be deleted. | | **Access-rights changes** | allowed / blocked | blocked | Whether the agent may grant or revoke user/group access. Off by default. | **Broadening access is not automatic.** An agent cannot silently raise its own permissions: expanding any axis requires your explicit confirmation (a form in the client, or a link to the session settings). Narrowing access takes effect immediately. ## What it cannot access or do * It cannot act outside the session's **project scope** — entities in other projects are refused. * In **read-only** sessions it cannot create, update, or delete anything. * In **data-restricted** sessions it cannot read or write numeric values, import table data, or inspect/run ETL for data. * It cannot **change access rights** or **delete project spaces** unless those axes are explicitly enabled. * It cannot reach **external systems** or use your **personal credentials** — it authenticates through its own token exchange. * It cannot connect to an unrecognized Valsight instance — the target instance is validated before any secret is sent. ## Connecting an AI client **Prerequisite:** the MCP server must be enabled for your Valsight instance. It is a premium feature, opted into per customer (see the availability note at the top of this page), so confirm your instance has it before you start. There is **no single, public MCP endpoint.** The server address is specific to your Valsight instance and contains your instance's URL — you connect your AI client to that per-instance address. Connecting is a two-part handshake: the client authenticates with **OAuth 2.0**, and the server exchanges that identity for access to your instance. 1. **Point your AI client at your instance's MCP endpoint.** Any AI client that supports MCP can connect. There is no single, standard way to add an MCP server — how you configure it depends on the client, so follow that client's own MCP setup instructions. 2. **Sign in when prompted.** Authentication uses your normal Valsight sign-in — the same flow you already use. 3. **Set the session scope.** You can steer what the session may do by asking the agent in plain language, or through the session-management page. Scope covers the target instance, project(s), access level, and data access — see [Session scope and permissions](#session-scope-and-permissions) for the axes and their defaults. **Sessions and sign-in:** a session ends after a period of inactivity, when access is revoked, or when an administrator ends it. Your Valsight sign-in stays valid for **12 hours**, after which you sign in again. ## Good to know * **Write is the default:** an MCP session can change your models unless it is connected as `read_only`. Scope it deliberately. * **Numeric data is a separate switch:** `data access` is independent of `access level` — a read-only session can still be restricted from seeing numbers, and a write session can still be blocked from them. * **Every call is audited:** tool calls are logged per session for traceability. ## Related * [Valsight AI](/ai-assistant/): overview of both ways to use Valsight AI * [Using the AI Assistant](/using-the-ai-assistant/): the in-app Assistant — how to phrase questions and what to expect * [FAQ: Valsight MCP integration](/frequently-asked-questions-valsight-mcp-integration/): connecting, security, and prerequisites The Valsight MCP server is itself an MCP endpoint over HTTP-stream transport with OAuth 2.0 (RFC 9728 protected-resource metadata). Tools are exposed under the `valsight_*` namespace and gated by the session axes above: access level (read\_only/write), data access (full/restricted), project scope, project-delete, and access-rights-modify. Broadening any axis requires user confirmation. Document concrete tool names, arguments, and return shapes here if a per-tool reference is added later. --- # Valsight Pluggable Modules - Security Architecture URL: https://docs.valsight.ai/valsight-pluggable-modules-security-architecture/ Description: As part of consulting projects, Valsight or a consulting partner may develop specialized Modules that allow the user to process Excel in specific formats, or… As part of consulting projects, Valsight or a consulting partner may develop specialized Modules that allow the user to process Excel in specific formats, or allows to display or modify data from the Valsight Simulation scenarios. These modules are customizations that are offered on top of the core Valsight Application. To ensure that all existing permissions and security precautions are met, these pluggable modules are limited to the following operations within Valsight: * Access the Application through the API as the current user - limiting all operations to that users' scope * Cannot load external scripts. All needed scripting is embedded in the HTML file, thereby allowing the Pluggable Module to be audited at a certain point in time. --- # Versioning URL: https://docs.valsight.ai/versioning/ Description: Versioning Valsight tracks two kinds of versioning: scenario versioning and assumption versioning. --- # Versioning of Exports URL: https://docs.valsight.ai/versioning-of-exports/ Description: The Export Manager allows you to version your export. This means, that when creating the first export for a scenario, we are creating an export for you along… The Export Manager allows you to version your export. This means, that when creating the first export for a scenario, we are creating an export for you along with its first version. The export and its versions share the given name, which can be changed at any time to a custom or different name. You can create a new version of an export at any time on an available export from within the Export Manager. Simply click on the three-dot menu of an export and click “Create new Version”. If no custom name is assigned, a custom name will be generated. It is recommended to add additional information about the version in the description. ![image-20240405-152224.png](./images/5551980579.png) To view the versions of an export simply click on an export to view the version history page. Here you can see a list of all available versions of an export, as well as delete and download them through the three-dot menu. ![image-20240606-164358.png](./images/5559058484.png) ## Related * [Export Manager](/export-manager/) --- # Visualizing Data URL: https://docs.valsight.ai/visualizing-data/ Description: Choose a chart type, create a chart, format it so it reads well, and present the result to others. Charts, bridges and tables are how simulation results are read. This section covers choosing the right one, building it, making it readable, and presenting the finished sheet to others. ## Start here if you want to: | If you | Go to | | ------------------------------------------------------------ | ------------------------------------------------------------------------ | | Work out which chart, table or tile fits your data | [Chart Types](/chart-types/) | | Add a chart to a worksheet and point it at your data | [Creating Charts](/creating-charts/) | | Choose what a chart shows, and at which level of aggregation | [Data Display in Charts and Tables](/data-display-in-charts-and-tables/) | | Sort, scale, color or restyle a chart you already have | [Formatting Charts](/chart-configuration/) | | Explain a difference between scenarios or between periods | [Bridges](/bridges/) | | Let people simulate on the worksheet itself | [Simulations](/chart-types/#simulations) | | Share a finished sheet as a fixed, view-only snapshot | [Using the Presentation Mode](/using-the-presentation-mode/) | --- # Währungseffekte URL: https://docs.valsight.ai/waehrungseffekte/ Description: Währungseffekte [Währungseffekte.pdf](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989793814_Waehrungseffekte.pdf) [FX data.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5990449161_FX-data.xlsx) [Legal Entity dim.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989924869_Legal-Entity-dim.xlsx) [Eingabewährung dim.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5989761061_Eingabewaehrung-dim.xlsx) [Ausgabewährung dim.xlsx](https://vs-documentation-assets.fsn1.your-objectstorage.com/files/5990219790_Ausgabewaehrung-dim.xlsx) --- # Warnings on Nodes URL: https://docs.valsight.ai/warnings-on-nodes/ Description: Nodes with active validation errors display a warning icon in their top-right corner. This lets you spot and address issues directly in the Model Editor with… Nodes with active validation errors display a warning icon in their top-right corner. This lets you spot and address issues directly in the Model Editor without opening the central validation view. ## What it shows * A single icon appears per node, regardless of how many warnings exist * Hover the icon to see the tooltip: "Validation warning(s)" * Click the icon to open the Inspector on the right and switch it to the node's **Validations** tab, which lists that node's warnings Video: [Validation on nodes](https://vs-documentation-assets.fsn1.your-objectstorage.com/videos/6883606529_Validation-on-nodes.mov) ## Show / hide Toggle visibility under **Layout → Node Display → Show Validations** in the Inspector. Icons are **off by default**, so a fresh project shows none until you switch the setting on. This setting is saved per user and project. ![Show validations toggle highlight.png](./images/6883573799.png) --- # Workflows URL: https://docs.valsight.ai/workflows/ Description: Workflows are Valsight's internal project management tools that enable smooth collaboration between multiple business units and levels by sharing scenarios i… Workflows are Valsight's internal project management tools that enable smooth collaboration between multiple business units and levels by sharing scenarios in a controlled and transparent manner. We recommend using Workflows for larger, cross-departmental projects such as multi-year planning and forecasting cycles. As Workflows can be reused, they are also ideal for recurring projects or processes such as forecasts. ![image-20240701-172628.png](./images/5599854673.png) **How it Works:** A Workflow consists of multiple workflow steps. Each step is associated with a workspace, and thus, with a group of users. It is possible to set dependencies between steps, requiring one user to wait until another user has submitted their measures and assumptions before starting their simulations. Workflows allow you to manage access, oversee submissions, and control who and when is reviewing steps and submissions, ensuring a fully transparent and controlled process. ![image-20240701-172807.png](./images/5600083981.png) **Status:** A Workflow can have multiple scenarios. Each step and workspace can work on and submit their assumptions into multiple scenarios. Each scenario in each step has a status, making it easier for the admin to manage the project and monitor its progress. The statuses are as follows: * **Open:** Work on this scenario has not started yet or has not been submitted. * **Preview:** Work has been submitted and is ready to be reviewed or accepted if necessary. * **Review:** The work has been imported by another user and accepted (if applicable). * **Done:** If necessary, another user can review this step again. After everything has been submitted and accepted, the step can be promoted to done. From this moment onwards, no more changes can be submitted to this scenario. Only an admin can now demote the step again. ![image-20240701-172858.png](./images/5600083988.png) See the [Admin documentation](/creating-managing-workflows-for-admins/) to learn how to configure and manage a Valsight Workflow correctly. To learn how to import and submit scenarios and steps as an individual contributor, view the [individual contributor Workflow documentation](/using-workflows-for-contributors/). --- # Working with different Model Baselines URL: https://docs.valsight.ai/working-with-different-model-baselines/ Description: Baselines allow you to maintain multiple versions of logic and results within a single model. They make it possible to compare different scenarios, such as Ac… Baselines allow you to maintain multiple versions of logic and results within a single model. They make it possible to compare different scenarios (such as Actuals, Budget, or Plan) without duplicating the model structure. ## How they work A baseline represents a **scenario-specific version of logic** inside the same model. All baselines share: * The same nodes * The same structure * The same dimensions and data connections What differs per baseline: * Node formulas and operations * Assumptions and resulting values This means one node can behave differently depending on the selected baseline, while still being the same node conceptually. Baselines make scenario comparison straightforward because all versions live in one consistent structure. ## Setup Baselines are created and managed at the project level. ![Operation per baseline\_Model Editor.png](./images/6698205189.png) [Once a baseline exists](/baselines/), node logic can be adapted per baseline as needed. 1. Activate the *Operation per baseline* toggle 2. Select the desired baseline from the dropdown 3. The formula editor will always display the current baseline ## Using the feature * Use baselines to separate Actuals from forward-looking plans. * Create multiple planning versions to compare alternative assumptions. * Keep older logic available when methodologies change. * Switch baselines to review and compare results consistently. > Baselines are not a replacement for scenarios or workspaces. ## Access & permissions Baselines are project-level objects, so edit access to a model is not enough to manage them. Creating or changing a baseline needs all three of: * **Edit rights on the project**, or edit rights on that baseline together with view rights on the project * The **Model** user type or higher * An **unlocked project**, since locking one blocks baseline changes along with everything else Edit access to a model while holding only view access to the project does not allow baseline management. ## FAQ **Are baselines separate models?** No. They are different versions of logic within the same model. **Does changing the baseline affect only one node?** No. Baselines apply at the model level. When you change the baseline, all nodes are recalculated using the logic and assumptions of that baseline. **Can I compare baselines directly?** Yes. Baselines are designed to make scenario comparison easy. **Should I create a new model instead of a baseline?** Use a new model only if the structure needs to change. Use baselines when the structure stays the same. **When should I use a baseline instead of a scenario?** Use a baseline to define the underlying version of your model (like Actuals or Plan). Use scenarios to test changes on top of that baseline. ## Related * [Model Editor UI](/model-editor-ui/) * [Baseline Indicator on Nodes](/baseline-indicator-on-nodes/) --- # Working with the Model Definition Editor URL: https://docs.valsight.ai/working-with-the-model-definition-editor/ Description: Valsight allows to edit models in a textual representation. In the admin UI, select Projects, then Models, find the model you want to edit and open the "Defi… Valsight allows to edit models in a textual representation. In the admin UI, select Projects, then Models, find the model you want to edit and open the "Definition Editor". ![Screen Shot 2017-11-28 at 10.14.59.png](./images/5094190517.png) ![Screen Shot 2017-11-28 at 10.15.13.png](./images/5094190512.png) In the definition editor, you can edit formulas or use you favorite text editor to do bulk changes. --- # Worksheet Filter URL: https://docs.valsight.ai/worksheet-filter/ Description: Worksheet filters are the second level of filter available in Valsight. Worksheet filters are the second level of filter available in Valsight. Worksheet filters allow users to easily and quickly adjust the focus of a worksheet. Worksheet filters affect all set chart filters which allows a quick change of focus of a sheet without the need to change all chart filters manually. A worksheet filter is **not a personal view**. It is stored on the worksheet itself, so it survives a reload and applies to **every user** who opens that sheet. Setting one requires only view permission on the workspace, not edit permission, so any user who can open the workspace can change what everyone else sees. For filtering that affects only your own view, use [chart filters](/chart-filter/). To apply or edit worksheet filters, open the options of the selected sheets and either hide or show the worksheet filters. ![image-20230920-115821.png](./images/6034489386.png)![image-20230919-132341.png](./images/6034489393.png) > Worksheet filters are limited by the applied workspace filters. --- # Workspace Filter URL: https://docs.valsight.ai/workspace-filter/ Description: A workspace filter are the highest level of filter to be set. A workspace filter is the **highest level of filter** to be set. Workspace filters help you organize your workspace and allow quick and easy access to specific information contained within workspaces and worksheets. They are filters that apply to an entire workspace, including all worksheets belonging to a workspace, all charts positioned within these worksheets, and the line-items in the Scenario Manager. A workspace filter is **not a personal view**. It is stored on the workspace itself, so it restricts the displayed data for **all users** of that workspace to the selected filter values. For dynamic filtering, use [worksheet filters](/worksheet-filter/) or [chart filters](/chart-filter/) instead. By applying workspace filters, you can choose which dimensions and levels should be included in your visualizations. This way, you can filter out specific dimensions, levels, or time periods to quickly adapt your charts and tables. A filter only affects data that carries the filtered level. If a chart is not dimensioned by the level you filtered on, the filter is **silently ignored** for that chart, which keeps showing full, unfiltered totals, and nothing in the interface says so. A workspace filter on Region, for example, restricts only the charts whose data has a Region level; a company-wide total without Region is unaffected. To apply workspace filters, click on the funnel icon in the header bar and select “Add filter”. You can then assemble a filter by choosing the conditions you want to filter for. > **Anyone who can open the workspace can change its filters.** Editing a workspace filter deliberately needs only view permission, not edit permission. Since the filter is stored on the workspace and applies to everyone, any user of a workspace can change what all the others see. ![Applying Workspace Filters.gif](./images/6034194463.gif) Each filter pairs a set of level values with an operator. Six are available: `=`, `>`, `≥`, `<`, `≤` and `≠`. `=` and `≠` give you the familiar include and exclude, while the four ordering operators are useful on levels with a natural order, such as time: `≥ 2024` keeps everything from 2024 onwards without listing the years. > **A filter with all values selected accepts only `=`.** Choosing any other operator is refused with ‘For filters where all level values are selected, only the ‘=’ is allowed as an operation.’ Deselect a value first, or leave the operator on `=`. --- # Workspace Validation URL: https://docs.valsight.ai/workspace-validation/ Description: Check that your workspace scenarios and model logic function correctly together. Check that your **workspace scenarios** and **model logic** function correctly together. ## When to use it * After creating or modifying scenarios, to verify that results remain consistent * When investigating unexpected values in workspace charts or reports * As a routine check before sharing or presenting workspace results ## How it works Workspace validation checks four things: * **Validation nodes:** It evaluates the conditions defined in your model's [Validation Nodes](/validation-nodes/) across all active scenarios, catching logical errors that only surface when scenarios interact with model logic. * **Line-item dimensions:** It checks whether line-items added in scenarios have dimensional problems, such as referencing dimensions or level values that do not match the target node's shape or do not exist anymore. * **Line-items in shared scenarios:** The same dimension checks run again over every scenario you have imported, and over any scenario nested inside those. A problem in somebody else's shared scenario therefore surfaces in your workspace, reported against a line-item you did not create. * **Nodes limited to one assumption:** It flags scenarios that stack more than one assumption on a node whose **Single assumption per scenario** setting is on, see below. ## Nodes limited to one assumption **Single assumption per scenario** is a per-node toggle in the **Validation Settings** section of the [Node Editor](/node-editor/), next to **Validation Node**. It is off by default. Switch it on for a node where stacking two assumptions would double-count, and workspace validation then reports every scenario in which more than one assumption acts on that node. It catches three shapes: two line-items on the node, a line-item together with a scenario assumption, and two scenario assumptions. The message names both culprits, for example "Node 'Price' is limited to a single assumption, but has multiple active: line-item 'Discount', line-item 'List price uplift'". The setting reports, it does not block. Nothing stops a user activating a second assumption on the node, so the conflict surfaces in workspace validation rather than at the moment it is created. This provides a deeper check than model validation, which only verifies syntax and structure. ## Running a workspace validation 1. Open a **Workspace** or the **Scenario Manager**. 2. Click the **validation icon**. ![image-20260402-095610.png](./images/6860406870.png) Workspace validation can also be set to run automatically, removing the need for manual checks. ## Validation states The validation icon has three possible states: | Symbol | Status | Meaning | | :-----------------------------------------------------------------: | --------------- | -------------------------------------------------------------------------------------------------- | | ![Valid validation icon](./images/validation-valid.svg) | **Valid** | The workspace, its charts, and all scenarios are working correctly. | | ![Invalid validation icon](./images/validation-invalid.svg) | **Invalid** | The workspace or its components have issues. Click the icon to see details. | | ![Out-of-date validation icon](./images/validation-out-of-date.svg) | **Out of date** | Changes have been made since the last validation. Only shown when validation is set to **manual**. | ## FAQ **How does workspace validation differ from model validation?** Model validation checks formula syntax and data compatibility. Workspace validation checks whether validation node conditions are met across active scenarios and if the dimensions between line items and nodes align. **Do I need validation nodes for workspace validation to work?** Not strictly. Workspace validation also checks line-item dimensions independently. However, validation nodes are needed if you want custom result-level checks across scenarios. **Can I automate workspace validation?** Yes. Validation can be configured to run automatically when changes are made. ## Related * [Model Validation](/model-validation/): check model syntax and data compatibility * [Validation Nodes](/validation-nodes/): define the custom conditions that workspace validation checks --- # Workspaces URL: https://docs.valsight.ai/workspaces/ Description: - Workspaces are a fundamental part of Valsight and allow you to perform simulations. They are a sandbox in which you can create simulation scenarios and vis… Workspaces are a fundamental part of Valsight and allow you to perform simulations. They are a sandbox in which you can create simulation scenarios and visualize the resulting data, as well as analyze and compare them, using tools such as charts and tables. A simulation workspace is always based on an underlying model that structures the relevant data in nodes and defines their calculation logic. The workspace header carries an **Open Underlying Model** button that takes you straight to that model in the model editor. Simulation scenarios are local to the simulation workspace and consist of a list of assumptions assigned to the scenario. These assumptions describe changes to the base data of the model and can be individually activated or deactivated for a specific scenario. Using scenarios and assumptions allows you to analyze different assumed situations and results, enabling valuable insights into the changing outcomes of complex business models. ![image-20230531-094243.png](./images/5148016666.png) ## Core functions Workspaces combine three core functions that enable a controlled and comprehensive analysis of simulations and generated data. The core functions are: * [**Scenario Manager**](/scenario-manager/)[:](#) Contains an overview of all assumptions, line-items, and scenarios that change your base data * [**Worksheets**](/workspaces/)[:](#) Allow you to dashboard graphs, tables, and other representations of your data * [**Charts**](/data-display-in-charts-and-tables/): Display simulated data in a readable and comprehensive way. ## Scenario Manager The [Scenario Manager](/scenario-manager/) can be used to create assumptions and line-items to simulate scenarios based on your driver model. Scenarios represent different situations that are based on different sets of assumptions. [Assumptions](/creating-assumptions/) are groups of line-items. They structure incremental changes to their baseline data into manageable groups of economic factors. Examples are "Base assumptions", containing line-items such as "Inflation" or "COGS", or "Market assumptions", containing line-items like "Change of Market Share" or "Change of Market Volume". Line-items contain changes to the data of a single node and allow detailed changes in the data sets. They can be assigned to different assumptions to control precisely which changes to what data you want to examine. Line-item data can either be adjusted based on adding or subtracting changes to the base data or be set to specific results for easier control. This can be done in the line-item data view. They can also contain different variants ([Line-Item Variants](/line-item-variants/)), which are versions of the same line-item. ![image-20230531-094432.png](./images/5148409885.png) ## Worksheets Worksheets display your charts and tables in tiles, to grant a dashboard overview. You can create multiple worksheets based on the same scenarios and assumptions. Your worksheets are listed in the tab bar at the bottom of the page. Scrolling through the sheets can be done via the arrows in the tab bar. Charts are configurable and can be changed in size and color to increase readability and control the manner information is visualized. To provide a focus for a worksheet, [worksheet filters](/filters-in-valsight/) can be used. Worksheets can be created via the “+” button in the lower left corner of a worksheet. ![image-20240124-092910.png](./images/5350424602.png) ### Sheet groups Worksheets do not have to stay a flat list. **Create Group** in the tab bar makes a group with a name and a color, and **Assign to group** puts a worksheet into it; **Ungroup** takes it back out. A group can be renamed with **Edit Group** and copied with **Duplicate Group**, and the same settings are reachable in bulk from the **Sheet and Group Configuration** dialog. > Deleting a group can take its worksheets with it. The confirmation reads ‘Delete group … and all {n} associated sheets? … This action cannot be undone.’, and the configuration dialog counts the groups, sheets and charts a save would remove. Ungroup the worksheets first if you only want to dissolve the group. ## Charts Another core feature of a workspace is the creation of charts and tables. Each chart has the functionality to be shown in a full screen mode via a button in the upper right corner, to simplify presentations or to highlight a certain chart. The most common chart types are: * **Line charts** display its data series as connected lines. * **Column charts** display data using vertical bars; multiple data series can be displayed next to each other. * **Stacked column/bar** chart displays its data using vertical bars and stacks the bars on top of each other if multiple data series are displayed. * **Scenario bridge/Bridge charts** display the effect of active assumptions; you can show the effect of all assumptions or the effect of each line item inside the assumptions. * **Area charts** are extensions of the line chart with the area below a line being filled with color. These five are all variants of the same flexible chart. Other tile types exist alongside them, among them KPI tiles, sliders and split sliders, tree charts, input tables, text and image tiles and the Perspective Selector. Further Reading: [Chart Types](/chart-types/) ### Keeping charts up to date The workspace header carries a refresh button with a **Refresh Settings** popover offering **Manual** and **Auto**. On **Auto**, charts are recalculated as the workspace changes. On **Manual** they are not, and the workspace tells you so rather than showing stale numbers silently: * The refresh button turns orange, with the tooltip ‘Some charts in this sheet are potentially outdated. Click to refresh sheet.’ Up to date, it reads ‘All charts are up to date’. * An individual tile shows ‘Calculated at {timestamp}. This chart is potentially outdated.’ * A chart that has not been calculated at all renders ‘The chart has not been loaded.’ with a **Load** button. **Chart Editor** An important part of a chart is the editor. It grants you complete control over the configurations of any chart or table. Using the chart editor, you can configure the type of chart you want to use, on which node it should base, how the axes should be configured, and which levels and filters should be applied. Furthermore, there are additional formatting settings to configure the charts based on your needs. By applying filters and adjusting the chart settings, you can control directly which data, factors, and calculations are represented in your graphs. It is also possible to format data points or series, to make their influence on the chart visible. You can also add comparisons of specific data points to emphasize specific differences. Lastly, you can specifically adjust if the chart should contain grid lines, at what rate they should be displayed, and which limits the axes should adhere to. The full-screen preview mode immediately shows you the impact of your changes while you configure your chart. To exit the preview mode, you can either save your changes or discard them. ![image-20230602-084229.png](./images/5150048290.png) ## Step-by-Step approach 1. To create a simulation workspace, navigate to the list of workspaces by selecting "Workspaces" in the navigation bar on the left. You will see a list of all simulation workspaces you have access to. 2. Click the round plus button in the top right corner, give your new workspace a name, and select the model and scenario to base the workspace on. The selected scenario defines the data baseline that will be used as the basis for all simulations you create in your new workspace. 3. After clicking "Create workspace", your new workspace will appear in the list of workspaces. Click on it **once** to select it, and you will see details in the chart editor on the right. You can change and adjust all of them, most importantly the simulation horizon ([Changing the Time Horizon](/changing-the-time-horizon/)). This setting defines the time interval that will be used for all your simulations. 4. Open your workspace by clicking on its name. You will find it empty, without any charts or assumptions. You can continue by populating your workspace with new assumptions ([Assumptions & Line-Items](/assumptions-line-items/)) , sheets, charts, and scenarios via the '+' button in the lower-left corner, or the Scenario Manager button in the upper right corner. > A workspace that takes part in an ongoing [workflow](/workflows/) cannot be deleted. Valsight names up to three of the blocking workflows, plus a count of the remainder, and asks you to complete them first. The same applies to a workspace that other objects still link to. ## Related * [Validations](/validations/) * [Simulations & Analysis](/simulations-analysis/) --- # WOW_ABS URL: https://docs.valsight.ai/wow-abs/ Description: Default: ignoring missing values **Category:** [Compare periods](/compare-periods/) ## Overview The **WOW\_ABS** function **returns the absolute growth for each week compared to the previous week** (week-over-week). Use this function when you need the absolute difference between consecutive weeks. ## Syntax `WOW_ABS('Node' [, "MissingValueBehaviour"])` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ------------------ | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | -- | | **MissingValueBehaviour** | How missing values are treated. | Keyword | No | `"IGNORE_MISSING"` | **MissingValueBehaviour options:** * `"IGNORE_MISSING"`: Missing rows are skipped. This is the default. * `"MISSING_AS_ZERO"`: Missing rows are treated as 0. ## Watch out * This function is only available on projects that use the **week time dimension**. A project has either Year, Quarter, Month and Day or Iso-Year, Week and Day, never both, so on a month-dimension project the node fails with an error saying the Week level could not be found. The time dimension is chosen per project, see [Project Settings](/project-settings/). ## Examples ### Default: ignoring missing values This example shows WOW\_ABS with the default behavior. The missing week W05 is skipped and no result is produced for it. **Input node:** `'Profit'` | Week | Value | | -------- | ----- | | 2025-W01 | 200 | | 2025-W02 | 300 | | 2025-W03 | 450 | | 2025-W04 | 500 | | 2025-W06 | 100 | **Formula:** `WOW_ABS('Profit')` **Equivalent to:** `WOW_ABS('Profit', "IGNORE_MISSING")` | Week | WOW\_ABS Result | | -------- | --------------- | | 2025-W02 | 100 | | 2025-W03 | 150 | | 2025-W04 | 50 | ### Treating missing values as zero With MISSING\_AS\_ZERO, gaps are filled with 0, producing results for every week including those without input data. **Formula:** `WOW_ABS('Profit', "MISSING_AS_ZERO")` | Week | WOW\_ABS Result | | -------- | --------------- | | 2025-W01 | 200 | | 2025-W02 | 100 | | 2025-W03 | 150 | | 2025-W04 | 50 | | 2025-W05 | -500 | | 2025-W06 | 100 | | 2025-W07 | -100 | ## Related | Function | When to use instead | | ------------------------- | -------------------------------------------------------------------------------------- | | [WOW\_REL](/wow-rel/) | When you need the percentage change week-over-week instead of the absolute difference. | | [YOY\_ABS](/yoy-abs/) | When you need the absolute difference on a yearly basis instead of weekly. | | [DELTA\_ABS](/delta-abs/) | When you need the absolute change along any dimension, not just time. | --- # WOW_REL URL: https://docs.valsight.ai/wow-rel/ Description: Returns the relative growth for each week compared to the previous week (week-over-week). **Category:** [Compare periods](/compare-periods/) ## Overview The **WOW\_REL** function **returns the relative growth for each week compared to the previous week** (week-over-week). Use this function when you need the percentage change between consecutive weeks. ## Syntax `WOW_REL('Node' [, "MissingValueBehaviour"])` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ------------------ | | **Node** | Input node, specified using the node name in single quotes (e.g. `'Profit'`) | Node reference | Yes | -- | | **MissingValueBehaviour** | How missing values are treated. | Keyword | No | `"IGNORE_MISSING"` | **MissingValueBehaviour options:** * `"IGNORE_MISSING"`: Missing rows are skipped. This is the default. * `"MISSING_AS_ZERO"`: Missing rows are treated as 0. ## Watch out * This function is only available on projects that use the **week time dimension**. A project has either Year, Quarter, Month and Day or Iso-Year, Week and Day, never both, so on a month-dimension project the node fails with an error saying the Week level could not be found. The time dimension is chosen per project, see [Project Settings](/project-settings/). ## Examples ### Default: ignoring missing values This example shows WOW\_REL with the default behavior. The missing weeks are skipped and no result is produced for them. **Input node:** `'Profit'` | Week | Value | | -------- | ----- | | 2025-W01 | 200 | | 2025-W02 | 300 | | 2025-W03 | 450 | | 2025-W04 | 500 | | 2025-W06 | 100 | **Formula:** `WOW_REL('Profit')` **Equivalent to:** `WOW_REL('Profit', "IGNORE_MISSING")` | Week | Calculation | Result | | -------- | ----------------- | ------ | | 2025-W02 | (300 - 200) / 200 | 0.5 | | 2025-W03 | 150 / 300 | 0.5 | | 2025-W04 | 50 / 450 | 0.11 | ### Treating missing values as zero With MISSING\_AS\_ZERO, gaps are filled with 0, producing results for every week including those without input data. **Formula:** `WOW_REL('Profit', "MISSING_AS_ZERO")` | Week | Calculation | Result | | -------- | ----------------- | ------ | | 2025-W02 | (300 - 200) / 200 | 0.5 | | 2025-W03 | 150 / 300 | 0.5 | | 2025-W04 | 50 / 450 | 0.11 | | 2025-W05 | (0 - 500) / 500 | -1 | | 2025-W07 | (0 - 100) / 100 | -1 | 2025-W06 is not present in the result: even with MISSING\_AS\_ZERO, dividing by a zero previous value causes a division by zero, so the entry is dropped. ## Related | Function | When to use instead | | ------------------------- | ----------------------------------------------------------------------------- | | [WOW\_ABS](/wow-abs/) | When you need the absolute difference week-over-week instead of a percentage. | | [YOY\_REL](/yoy-rel/) | When you need the percentage change on a yearly basis instead of weekly. | | [DELTA\_REL](/delta-rel/) | When you need relative change along any dimension, not just time. | --- # XML Access URL: https://docs.valsight.ai/xml-access/ Description: All Valsight objects that are exposed via the REST API can be accessed in the XML format. All Valsight objects that are exposed via the REST API can be accessed in the XML format. Simply add the get parameter `format=xml` to the URL. For example, if `https://valsight-url/v1/projectSpaces` returns the JSON representation of objects, then `https://valsight-url/v1/projectSpaces?format=xml` returns the XML representation. --- # XOR URL: https://docs.valsight.ai/xor/ Description: Connects two inputs with the logical 'exclusive or' XOR and returns true (1) if exactly one of the input values is true and false (0) otherwise. **Category:** [Logical functions](/logical-functions/) ## Overview The **XOR** function **connects two inputs with the logical 'exclusive or' XOR** and returns true (1) if exactly one of the input values is true and false (0) otherwise. Use this function when you need a 1/0 flag that becomes true only if exactly one of two inputs is true. ## Syntax `XOR('Node1', 'Node2')` ## Parameters | Parameter | Description | Type | Required | | --------- | ----------------------------------------------------------------------------------- | -------------- | -------- | | **Node1** | First input node, specified using the node name in single quotes (e.g. `'Profit'`). | Node reference | Yes | | **Node2** | Second input node. | Node reference | Yes | ## Watch out * Both input nodes must have the same dimensionality; otherwise rows are excluded from the function output. * Both input nodes must contain the same levels, otherwise the function will consider only the more granular function while ignoring the function with fewer levels. **Example of the limitation:** the function is given two `EXPANDSINGLE()` inputs. However, one of the `EXPANDSINGLE()` functions possesses more levels than the other, resulting in different granularity. The function with more levels is the leading function. This leads to unexpected outputs from the `XOR()` function. ![Node formula and Data Preview showing an XOR of two EXPANDSINGLE inputs with mismatched granularity, illustrating the limitation](./images/5094231064.png) ## Examples ### Typical use This example shows that `XOR` returns 1 only when exactly one input is true. If both inputs are true or both are false, the result is 0. **Input node:** `'A'` | Year | Value | | ---- | ----- | | 2025 | 17 | | 2026 | 0 | | 2027 | 0 | | 2028 | 1 | **Input node:** `'B'` | Year | Value | | ---- | ----- | | 2025 | 1 | | 2026 | 0 | | 2027 | 1500 | | 2028 | 0 | **Formula:** `XOR('A', 'B')` | Year | XOR Result | | ---- | ---------- | | 2025 | 0 | | 2026 | 0 | | 2027 | 1 | | 2028 | 1 | ## Related | Function | When to use instead | | ----------------- | -------------------------------------------------------------------------------------------- | | [OR (\|\|)](/or/) | When at least one of the two inputs may be true instead of requiring exactly one to be true. | | [AND (&&)](/and/) | When both inputs must be true at the same time instead of exactly one of them. | --- # Y-Axis Breaks in Charts URL: https://docs.valsight.ai/y-axis-breaks-in-charts/ Description: A Y-axis break inserts a gap into the value axis so charts with large deviations or wide gaps in scale stay readable. A Y-axis break inserts a gap into the value axis so charts with large deviations or wide gaps in scale stay readable. Instead of small bars or numbers being squashed by a few very large values, you can "cut out" a range of the axis and bring all data points into a comfortable viewing range. ## What it is Y-axis breaks are configured per chart in the **Chart Editor**, under **Scales and Digits**. You define a single break by setting the range to cut out (**From**–**To**) and how large the remaining visual gap should be (**Breakpoint size**). On save, the chart renders the break at that position, and all data above and below the break is drawn at a readable scale. ![A chart with a Y-axis break cutting out an empty range](./images/y-axis-breaks.png) ## When to use it * When a few very large values flatten the rest of the chart and make smaller bars or lines hard to read * When there is a wide, empty gap in your value range that wastes vertical space * When presenting in boardroom settings, where every bar and number needs to be clearly legible ## Configuration 1. Open the chart in the **Chart Editor** and go to **Scales and Digits**. 2. Under **Settings**, below **Max Value**, turn on the **Show Y-Axis Breaks** toggle (off by default). 3. The break settings appear. Configure them as described below. 4. Save the chart. The break is drawn on the Y-axis. ![The Y-axis break settings in the Chart Editor under Scales and Digits](./images/y-axis-breaks-settings.png) ### Settings | Setting | Description | Default | | ---------------------- | ----------------------------------------------------------------------------------- | ------- | | **Show Y-Axis Breaks** | Turns the Y-axis break on or off for this chart. | Off | | **From** | The value where the break starts: the lower bound of the range cut out of the axis. | 0 | | **To** | The value where the break ends: the upper bound of the range cut out of the axis. | 0 | | **Breakpoint size** | The visual size of the gap shown in the chart at the break. | 1 | ### Supported chart types Y-axis breaks are available for the standard cartesian chart types: **line, column, bar, area, and mixed charts**, as well as **bridge (waterfall) charts**. ## Good to know * **Charts with multiple axes are not supported.** On these charts the **Show Y-Axis Breaks** toggle is disabled. * Only one break can be defined per chart. * The **From** and **To** values must sit within your data's value range for the break to be visible. --- # YOY_ABS URL: https://docs.valsight.ai/yoy-abs/ Description: The YOY_ABS function returns the absolute growth for each year compared to the previous year (year-over-year). The result is the difference current_year - previous_year in the same unit as the input. **Category:** [Compare periods](/compare-periods/) ## Overview The **YOY\_ABS** function **returns the absolute growth for each year compared to the previous year** (year-over-year). The result is the difference `current_year - previous_year` in the same unit as the input. Use this function when you need the absolute difference between consecutive years. ## Syntax `YOY_ABS('Node' [, "MissingValueBehaviour"])` **Example usage:** `YOY_ABS('Revenue')` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ------------------ | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | -- | | **MissingValueBehaviour** | How missing values in the time series are treated | Keyword | No | `"IGNORE_MISSING"` | **MissingValueBehaviour options:** * `"IGNORE_MISSING"`: Missing rows are skipped. A result row is only produced where both the current year and the previous year have values. This is the default. * `"MISSING_AS_ZERO"`: Missing rows are treated as 0. ## Output shape | Aspect | Behavior | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as input. | | Time range | With IGNORE\_MISSING, the first year is dropped and years adjacent to gaps are also removed. With MISSING\_AS\_ZERO, every year where either current or previous has data is included. | | Values | Each value is `current_year - previous_year`. The result keeps the same unit as the input. | | Row count | Reduced with IGNORE\_MISSING. With MISSING\_AS\_ZERO, can include years beyond the input data range (within the project horizon). | ## Watch out * The input must have a **Year** level. If the input does not contain a Year level, the function fails. * With **MISSING\_AS\_ZERO**, results appear at years where the input has no data. A missing current year treated as 0 produces a negative result equal to the previous year's value. A missing previous year treated as 0 produces a positive result equal to the current year's value. * With **MISSING\_AS\_ZERO**, years beyond the input data range (but within the project horizon) may appear in the result. ## Examples ### Default: ignoring missing values This example shows YOY\_ABS with the default behavior. **Input node:** `'Profit'` | Year | Value | | ---- | ----- | | 2025 | 200 | | 2026 | 300 | | 2027 | 450 | | 2028 | 500 | | 2030 | 100 | **Formula:** `YOY_ABS('Profit')` **Equivalent to:** `YOY_ABS('Profit', "IGNORE_MISSING")` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2026 | 300 - 200 | 100 | | 2027 | 450 - 300 | 150 | | 2028 | 500 - 450 | 50 | The first year (2025) has no previous year to compare against. The gap at 2029 causes both 2029 and 2030 to be excluded. ### Treating missing values as zero With MISSING\_AS\_ZERO, gaps are filled with 0, producing results for every year including those without input data. **Formula:** `YOY_ABS('Profit', "MISSING_AS_ZERO")` | Year | Calculation | Result | | ---- | ----------- | ------ | | 2025 | 200 - 0 | 200 | | 2026 | 300 - 200 | 100 | | 2027 | 450 - 300 | 150 | | 2028 | 500 - 450 | 50 | | 2029 | 0 - 500 | -500 | | 2030 | 100 - 0 | 100 | | 2031 | 0 - 100 | -100 | Year 2025 now has a result because its previous year (2024) is treated as 0. Year 2031 (beyond the input data but within the project horizon) also appears because 2030 has a value. ## Related | Function | When to use instead | | ------------------------- | ---------------------------------------------------------------------------------------------------- | | [YOY\_REL](/yoy-rel/) | When you need the percentage change year-over-year instead of the absolute difference. | | [DELTA\_ABS](/delta-abs/) | When you need the absolute change along any dimension, not just time (e.g. compare across products). | | [CAGR](/cagr/) | When you need compound growth over multiple periods, not just a single-period comparison. | --- # YOY_REL URL: https://docs.valsight.ai/yoy-rel/ Description: The YOY_REL function returns the relative growth for each year compared to the previous year (year-over-year). **Category:** [Compare periods](/compare-periods/) ## Overview The **YOY\_REL** function **returns the relative growth for each year compared to the previous year** (year-over-year). Use this function when you need the percentage change between consecutive years. ## Syntax `YOY_REL('Node' [, "MissingValueBehaviour"])` **Example usage:** `YOY_REL('Revenue')` ## Parameters | Parameter | Description | Type | Required | Default | | ------------------------- | ---------------------------------------------------------------------------- | -------------- | -------- | ------------------ | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | -- | | **MissingValueBehaviour** | How missing values in the time series are treated | Keyword | No | `"IGNORE_MISSING"` | **MissingValueBehaviour options:** * `"IGNORE_MISSING"`: Missing rows are skipped. A result row is only produced where both the current year and the previous year have values. This is the default. * `"MISSING_AS_ZERO"`: Missing rows are treated as 0. ## Output shape | Aspect | Behavior | | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as input. | | Time range | The first year is always dropped (no previous year to compare against). Additional years may be dropped depending on MissingValueBehaviour. | | Values | Each value is `(current_year / previous_year) - 1`. The result is a ratio, not a percentage. | | Row count | Reduced with IGNORE\_MISSING: the first year is removed, and so are years adjacent to gaps. With MISSING\_AS\_ZERO, the result can include years beyond the input data range (within the project horizon). | ## Watch out * The input must have a **Year** level. If the input does not contain a Year level, the function fails. * The result is a **ratio**, not a percentage: 0.5 means +50%, -1 means -100%. * **Division by zero** occurs when the previous year's value is 0. The affected cell is silently dropped (N/A). This is especially relevant with MISSING\_AS\_ZERO, where gaps are filled with 0. * With **MISSING\_AS\_ZERO**, the function produces results at years where only the previous year has data, treating the missing current year as 0. This leads to a result of -1 (a 100% decline). Be cautious when interpreting these results. ## Examples ### Default: ignoring missing values This example shows YOY\_REL with the default behavior. **Input node:** `'Profit'` | Year | Value | | ---- | ----- | | 2025 | 200 | | 2026 | 300 | | 2027 | 450 | | 2028 | 500 | | 2030 | 100 | **Formula:** `YOY_REL('Profit')` **Equivalent to:** `YOY_REL('Profit', "IGNORE_MISSING")` | Year | Calculation | Result | | ---- | ----------------- | ------ | | 2026 | (300 - 200) / 200 | 0.5 | | 2027 | (450 - 300) / 300 | 0.5 | | 2028 | (500 - 450) / 450 | 0.11 | The first year (2025) has no previous year to compare against. The missing year 2029 causes 2030 to also be excluded because no valid previous year exists. ### Treating missing values as zero With MISSING\_AS\_ZERO, gaps are filled with 0. This produces results for every year but can cause division by zero when the previous year has no data. **Formula:** `YOY_REL('Profit', "MISSING_AS_ZERO")` | Year | Calculation | Result | | ---- | ----------------- | ------ | | 2026 | (300 - 200) / 200 | 0.5 | | 2027 | 150 / 300 | 0.5 | | 2028 | 50 / 450 | 0.11 | | 2029 | (0 - 500) / 500 | -1 | The missing year 2029 is treated as having value 0, which produces a -1 result (100% decline). Year 2030 attempts to divide by 0 (the previous year 2029 was treated as 0), so the entry is dropped from the result. ## Related | Function | When to use instead | | ------------------------- | ------------------------------------------------------------------------------------------ | | [YOY\_ABS](/yoy-abs/) | When you need the absolute difference to the previous year instead of a percentage. | | [DELTA\_REL](/delta-rel/) | When you need relative change along any dimension, not just time. | | [CAGR](/cagr/) | When you need compound growth over multiple periods instead of a single-period comparison. | --- # YTD URL: https://docs.valsight.ai/ytd/ Description: The YTD function returns year-to-date values by calculating a running sum per year over the lowest available time level, resetting at the start of each new year. **Category:** [Rollforward & time series](/rollforward-time-series/) ## Overview The **YTD** function **returns year-to-date values by calculating a running sum per year over the lowest available time level**. The cumulative sum resets at the start of each new year. Use this function when you want cumulative values within each year that reset at the start of a new year. ## Syntax `YTD('Node')` **Example usage:** `YTD('Revenue')` ## Parameters | Parameter | Description | Type | Required | | --------- | ---------------------------------------------------------------------------- | -------------- | -------- | | **Node** | Input node, specified using the node name in single quotes (e.g.`'Revenue'`) | Node reference | Yes | ## Output shape | Aspect | Behavior | | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Dimensionality | Same as input. | | Time range | Periods within a year are filled forward from the first available value to the end of the year. Missing periods at the start of a year are not filled. Years with no data at all are not included. | | Values | Cumulative sum within each year. Resets to zero at the start of each new year. | | Row count | Expanded. Gaps within a year are filled, but completely empty years remain absent. | ## Watch out * The input must have a time level that is **finer than the reset level**. For YTD that means any time level below Year; Year-level input is not sufficient. Which levels those are depends on the project: Quarter, Month or Day on a month-dimension project, Week or Day on a week-dimension one. * Missing periods **at the start of a year** are not filled. For example, if Q1 is missing but Q2 has data, the YTD starts from Q2. * Missing periods **within or at the end of a year** are filled with the last cumulative value. For example, if Q3 is missing, Q3 and Q4 carry forward the Q2 cumulative total. * This function forces the time dimension level links to match the dimension management configuration. Do not use this function if you want the node to have different level links than the dimensions. * The related functions **QTD** (Quarter-to-Date), **MTD** (Month-to-Date), and **WTD** (Week-to-Date) work the same way but reset at the start of each quarter, month, or week respectively. The three are not all available everywhere: a project has either the Week levels or the Quarter and Month levels, never both. WTD needs a week-dimension project, and QTD and MTD need a month-dimension one. ## Examples ### YTD with missing quarters This example shows the year-to-date accumulation over quarters, including how missing quarters inside a year are filled with the latest cumulative value while missing quarters at the start of a year are not added. **Input node:** `'Profit'` | Year | Quarter | Value | | ---- | ------- | ----- | | 2025 | 2025-Q1 | 150 | | 2025 | 2025-Q2 | 200 | | 2025 | 2025-Q3 | 250 | | 2026 | 2026-Q2 | 100 | | 2026 | 2026-Q3 | 50 | | 2026 | 2026-Q4 | 120 | | 2027 | 2027-Q1 | 100 | | 2027 | 2027-Q2 | 120 | | 2027 | 2027-Q4 | 140 | **Formula:** `YTD('Profit')` | Year | Quarter | YTD Result | | ---- | ------- | ---------- | | 2025 | 2025-Q1 | 150 | | 2025 | 2025-Q2 | 350 | | 2025 | 2025-Q3 | 600 | | 2025 | 2025-Q4 | 600 | | 2026 | 2026-Q2 | 100 | | 2026 | 2026-Q3 | 150 | | 2026 | 2026-Q4 | 270 | | 2027 | 2027-Q1 | 100 | | 2027 | 2027-Q2 | 220 | | 2027 | 2027-Q3 | 220 | | 2027 | 2027-Q4 | 360 | 2025-Q4 was filled with the cumulative sum (600) because Q3 was the last quarter with data. 2026-Q1 is not in the result because it was missing at the start of the year. 2027-Q3 carries forward the Q2 cumulative (220) because Q3 had no input data. ### YTD across multiple dimensions This example shows how YTD behaves across multiple dimensions with gaps within a year, fully empty years, and a broader project horizon. **Input node:** `'ProfitMultiDim'` | Product | Year | Quarter | Month | Value | | ------- | ---- | ------- | ------- | ----- | | A | 2025 | 2025-Q4 | 2025-10 | 50 | | A | 2025 | 2025-Q4 | 2025-11 | 30 | | A | 2026 | 2026-Q1 | 2026-01 | 30 | | A | 2026 | 2026-Q1 | 2026-02 | 40 | | A | 2026 | 2026-Q4 | 2026-11 | 110 | | A | 2027 | 2027-Q1 | 2027-01 | 30 | | A | 2027 | 2027-Q1 | 2027-02 | 50 | | B | 2025 | 2025-Q4 | 2025-11 | 20 | | B | 2025 | 2025-Q4 | 2025-12 | 60 | | B | 2026 | 2026-Q1 | 2026-03 | 70 | | B | 2026 | 2026-Q4 | 2026-11 | 130 | | C | 2025 | 2025-Q4 | 2025-12 | 80 | | C | 2027 | 2027-Q1 | 2027-02 | 100 | | D | 2026 | 2026-Q1 | 2026-02 | 40 | | D | 2027 | 2027-Q1 | 2027-01 | 60 | | D | 2027 | 2027-Q1 | 2027-03 | 70 | **Formula:** `YTD('ProfitMultiDim')` **Project Horizon:** 2024 to 2029 | Product | Year | Quarter | Month | YTD Result | | ------- | ---- | ------------------ | ------------------ | ---------- | | A | 2025 | 2025-Q4 | 2025-10 | 50 | | A | 2025 | 2025-Q4 | 2025-11 | 80 | | A | 2025 | 2025-Q4 | 2025-12 | 80 | | A | 2026 | 2026-Q1 | 2026-01 | 30 | | A | 2026 | 2026-Q1 | 2026-02 | 70 | | A | 2026 | 2026-Q1 to 2026-Q4 | 2026-03 to 2026-10 | 70 | | A | 2026 | 2026-Q4 | 2026-11 | 180 | | A | 2026 | 2026-Q4 | 2026-12 | 180 | | A | 2027 | 2027-Q1 | 2027-01 | 30 | | A | 2027 | 2027-Q1 | 2027-02 | 80 | | A | 2027 | 2027-Q1 to 2027-Q4 | 2027-03 to 2027-12 | 80 | | B | 2025 | 2025-Q4 | 2025-11 | 20 | | B | 2025 | 2025-Q4 | 2025-12 | 80 | | B | 2026 | 2026-Q1 | 2026-03 | 70 | | B | 2026 | 2026-Q2 to 2026-Q4 | 2026-04 to 2026-10 | 70 | | B | 2026 | 2026-Q4 | 2026-11 | 200 | | B | 2026 | 2026-Q4 | 2026-12 | 200 | | C | 2025 | 2025-Q4 | 2025-12 | 80 | | C | 2027 | 2027-Q1 | 2027-02 | 100 | | C | 2027 | 2027-Q1 to 2027-Q4 | 2027-03 to 2027-12 | 100 | | D | 2026 | 2026-Q1 | 2026-02 | 40 | | D | 2026 | 2026-Q1 to 2026-Q4 | 2026-03 to 2026-12 | 40 | | D | 2027 | 2027-Q1 | 2027-01 | 60 | | D | 2027 | 2027-Q1 | 2027-02 | 60 | | D | 2027 | 2027-Q1 | 2027-03 | 130 | | D | 2027 | 2027-Q2 to 2027-Q4 | 2027-04 to 2027-12 | 130 | **Key observations:** * All products keep their first value unchanged; nothing is added before the first data point in each year. * All periods with at least one value are filled forward until the end of the year. * Completely empty years are left out (e.g. B for 2027, C for 2026). * No values for 2028 and 2029 (end of horizon) are added, as these would be new years with no data. ## Related | Function | When to use instead | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `QTD` | When the cumulative sum should reset every quarter instead of every year (not available on projects with the week dimension). | | `MTD` | When the cumulative sum should reset every month instead of every year (not available on projects with the week dimension). | | `WTD` | When the cumulative sum should reset every week (only available on projects with the week dimension). See: [Project Settings](/project-settings/) | | [RUNNINGSUM](/runningsum/) | When you want a running total across the full time axis without a yearly reset. |