Skip to main content

Prerequisites

  • Access to the risksheet.json configuration file (via the configuration editor or direct file editing)
  • Understanding of which Polarion fields (bindings) hold the source data for your calculations
  • Familiarity with JavaScript expression syntax

Step 1: Define the Formula in the Formulas Object

Open your risksheet.json and add a named formula to the top-level formulas object. Each formula is a JavaScript function that receives an info parameter containing the current row data.
{
  "formulas": {
    "commonRpn": "function(info){ var value = info.item['occ']*info.item['det']*info.item['sev']; return value?value:null;}"
  }
}
The info object provides access to:
PropertyDescription
info.itemThe current row’s data object, keyed by column id / binding
info.item['<binding>']Value of any column in the same row (use the column id as the key)
Always return null when source values are missing or zero to prevent displaying misleading results. The pattern return value ? value : null; ensures blank cells instead of zeros when inputs are incomplete.

Step 2: Create the Calculated Column

Add a column entry in the columns array and reference your named formula by setting the formula property to the formula name.
{
  "columns": [
    {
      "id": "rpn",
      "header": "RPN",
      "formula": "commonRpn",
      "width": 60
    }
  ]
}
Key column properties for calculated columns:
PropertyDefaultDescription
formulaNoneName of the formula defined in the formulas object
readOnlyfalse (auto-set to true)Automatically becomes read-only when formula is set
typeauto-detectedData type inferred from binding; override explicitly if needed
widthautoColumn width in pixels
headercolumn idDisplay text shown in the column header
level1Hierarchical level at which the column appears
filterabletrueControls whether users can filter by this column’s values
cellRenderernoneOptional custom cell renderer function name
When you set the formula property on a column, Risksheet automatically sets readOnly to true. You do not need to (and should not) manually set readOnly for formula columns. This prevents users from overwriting computed values.

Step 3: Build Common Formula Patterns

RPN Calculation (Severity x Occurrence x Detection)

The standard Risk Priority Number formula multiplies three rating values. Most FMEA workflows require both an initial RPN and a revised RPN (after mitigations):
{
  "formulas": {
    "commonRpn": "function(info){ var value = info.item['occ']*info.item['det']*info.item['sev']; return value?value:null;}",
    "commonRpnNew": "function(info){ var value = info.item['occNew']*info.item['detNew']*info.item['sevNew']; return value?value:null; }"
  }
}
Then add two columns referencing these formulas:
{
  "columns": [
    {
      "id": "rpn",
      "header": "RPN (Initial)",
      "formula": "commonRpn",
      "width": 70,
      "headerGroup": "Initial Rating"
    },
    {
      "id": "rpnNew",
      "header": "RPN (Revised)",
      "formula": "commonRpnNew",
      "width": 70,
      "headerGroup": "Revised Rating"
    }
  ]
}

Combining Fields from Linked Items

You can build formulas that concatenate or transform values from linked upstream items. For example, to combine an ID and title into a single display value:
{
  "formulas": {
    "combinedIdTitle": "function(info){ var id = info.item['linkedItemId']; var title = info.item['linkedItemTitle']; return id && title ? id + ' - ' + title : (id || title || null); }"
  }
}
Since version 24.9.1, the risksheet.ds.getMasterRowsByColumnValue() function enables aggregating data from downstream risk items into a parent row. This is critical for FMEA workflows where a process step needs to summarize characteristics from its child risk items — for example, collecting unique enum values from multiple risks or summing numeric fields across related items. Formulas using this function can also be written in the risksheetTopPanel.vm file using JavaScript.

Conditional Value Formula

Return different values based on cell data for risk classification:
{
  "formulas": {
    "riskLevel": "function(info){ var rpn = info.item['rpn']; if(!rpn) return null; if(rpn <= 150) return 'Low'; if(rpn <= 350) return 'Medium'; return 'High'; }"
  }
}

Conditional Column Editability via Formulas and Cell Decorators

You can use the systemReadOnlyFields pattern with cellDecorators to conditionally toggle column editability based on enum values. For example, to make a column read-only when a status enum is set to “approved”:
{
  "cellDecorators": {
    "conditionalReadonly": "function(info){ if(info.item['status'] === 'approved'){ info.item.systemReadOnlyFields = info.item.systemReadOnlyFields || []; info.item.systemReadOnlyFields.push('description'); } }"
  }
}
Enterprise FMEA/HARA implementations often require conditional field editability based on enum values (for example, making risk evaluation criteria read-only after approval). Test the systemReadOnlyFields approach thoroughly in your environment, as it interacts with both column-level and item-level permission settings.

Step 4: Add Conditional Formatting to Calculated Columns

Pair your calculated columns with cellDecorators and styles for visual risk indicators. This creates color-coded cells based on the computed value:
{
  "cellDecorators": {
    "rpn": "function(info){ var val = info.value; $(info.cell).toggleClass('boldCol', true ); $(info.cell).toggleClass('rpn1', val>0 && val <= 150 ); $(info.cell).toggleClass('rpn2', val > 150 && val <= 350); $(info.cell).toggleClass('rpn3', val > 350);}"
  },
  "styles": {
    ".boldCol": "font-weight:600;",
    ".rpn1": "background-color: #eaf5e9 !important;color: #1d5f20 !important;",
    ".rpn2": "background-color: #fff3d2 !important; color: #735602 !important;",
    ".rpn3": "background-color: #f8eae7 !important;color: #ab1c00 !important;"
  }
}
The decorator function receives info.value (the computed formula result) and info.cell (the DOM element), allowing you to toggle CSS classes based on thresholds:
RPN RangeStyle ClassAppearance
1 — 150rpn1Green background (low risk)
151 — 350rpn2Yellow background (medium risk)
> 350rpn3Red background (high risk)
diagram

Step 5: Apply Formula-Based Styling to Row Headers

You can also apply formula-based conditional formatting to row headers using the headers.rowHeader.renderer property. This colors the entire row header based on a data value, providing an at-a-glance risk indicator:
{
  "headers": {
    "rowHeader": {
      "renderer": "rowHeaderRpnNew"
    }
  },
  "cellDecorators": {
    "rowHeaderRpnNew": "function(info){ var val = info.item['rpnNew']; $(info.cell).toggleClass('rpn1', val>0 && val <= 150 ); $(info.cell).toggleClass('rpn2', val>0 && val > 150 && val <= 350); $(info.cell).toggleClass('rpn3', val>0 && val > 350);}"
  }
}
This colors each row’s header cell based on the revised RPN value of that risk item. When scanning a large FMEA table, you can immediately spot high-risk rows by their red header cells.
If a formula column is hidden from the Risksheet view (via column visibility settings or saved views), its formula does not execute. This means any cell decorator or other column that depends on the hidden formula column’s value will show stale or incorrect data. If a title column uses a formula and is hidden during item creation, the resulting Polarion work item may have an incorrect title (just a number instead of the computed value). Keep formula columns visible during item creation, or use the Check stored formulas feature (available since v24.5.1) to reconcile stored values after the fact.

Step 6: Verify Your Configuration

  1. Save your risksheet.json changes
  2. Refresh the Risksheet page in your browser
  3. You should now see the calculated column displaying computed values automatically
  4. Verify that the column is read-only — clicking a formula cell should not open an editor
  5. Change a source value (for example, update a severity rating) and confirm the formula recalculates immediately
  6. Check that cell decorators apply the correct color coding based on the formula result
After adding or modifying formulas, use the Check stored formulas feature to scan all rows and update any stored values that differ from the current formula result. This is especially important after changing formula logic on an existing Risksheet with historical data. The feature detects differences between the current formula result and the stored value, and marks affected items for update.

Complete Example

A full risksheet.json snippet for an FMEA table with initial and revised RPN calculations, conditional formatting, and row header coloring:
{
  "formulas": {
    "commonRpn": "function(info){ var value = info.item['occ']*info.item['det']*info.item['sev']; return value?value:null;}",
    "commonRpnNew": "function(info){ var value = info.item['occNew']*info.item['detNew']*info.item['sevNew']; return value?value:null; }"
  },
  "columns": [
    { "id": "sev", "header": "Severity", "type": "rating:severity", "width": 80, "headerGroup": "Initial Rating" },
    { "id": "occ", "header": "Occurrence", "type": "rating:occurrence", "width": 80, "headerGroup": "Initial Rating" },
    { "id": "det", "header": "Detection", "type": "rating:detection", "width": 80, "headerGroup": "Initial Rating" },
    { "id": "rpn", "header": "RPN", "formula": "commonRpn", "width": 60, "headerGroup": "Initial Rating" },
    { "id": "sevNew", "header": "Severity", "type": "rating:severity", "width": 80, "headerGroup": "Revised Rating" },
    { "id": "occNew", "header": "Occurrence", "type": "rating:occurrence", "width": 80, "headerGroup": "Revised Rating" },
    { "id": "detNew", "header": "Detection", "type": "rating:detection", "width": 80, "headerGroup": "Revised Rating" },
    { "id": "rpnNew", "header": "RPN", "formula": "commonRpnNew", "width": 60, "headerGroup": "Revised Rating" }
  ],
  "cellDecorators": {
    "rpn": "function(info){ var val = info.value; $(info.cell).toggleClass('boldCol', true ); $(info.cell).toggleClass('rpn1', val>0 && val <= 150 ); $(info.cell).toggleClass('rpn2', val > 150 && val <= 350); $(info.cell).toggleClass('rpn3', val > 350);}",
    "rpnNew": "function(info){ var val = info.value; $(info.cell).toggleClass('boldCol', true ); $(info.cell).toggleClass('rpn1', val>0 && val <= 150 ); $(info.cell).toggleClass('rpn2', val > 150 && val <= 350); $(info.cell).toggleClass('rpn3', val > 350);}",
    "rowHeaderRpnNew": "function(info){ var val = info.item['rpnNew']; $(info.cell).toggleClass('rpn1', val>0 && val <= 150 ); $(info.cell).toggleClass('rpn2', val>0 && val > 150 && val <= 350); $(info.cell).toggleClass('rpn3', val>0 && val > 350);}"
  },
  "styles": {
    ".boldCol": "font-weight:600;",
    ".rpn1": "background-color: #eaf5e9 !important;color: #1d5f20 !important;",
    ".rpn2": "background-color: #fff3d2 !important; color: #735602 !important;",
    ".rpn3": "background-color: #f8eae7 !important;color: #ab1c00 !important;"
  },
  "headers": {
    "rowHeader": {
      "renderer": "rowHeaderRpnNew"
    }
  }
}

See Also

KB ArticlesSupport TicketsSource Code
  • AppConfig.ts
  • AppConfigHelper.ts
  • PolarionAppConfigManager.java
  • risksheet.json
  • ConfigureColumnsCommand.ts