Skip to main content

Basic Formula Structure

Formulas are JavaScript function declarations or arrow functions that receive an info parameter object:
// Traditional function syntax
function(info) {
  return info.item['severity'] * info.item['occurrence'];
}

// Arrow function syntax
(info) => {
  return info.item['severity'] * info.item['occurrence'];
}

// Inline arrow function
(info) => info.item['severity'] * info.item['occurrence']
All three syntaxes are valid in RISKSHEET configurations.

Formula Parameter: info Object

Every formula receives a single parameter object info that provides access to row data and grid context:
PropertyTypeDescriptionExample
info.itemobjectKey-value object containing all column data for the current row. Access values via column binding name.info.item['severity'], info.item['status']
info.cellHTMLElementReference to the DOM element rendering this cell. Used with cell decorators for styling, not typical in formulas.$(info.cell).toggleClass('highlight')
info.rownumberZero-based row index in the gridinfo.row → 0, 1, 2, …
info.colnumberZero-based column index in the gridinfo.col → 0, 1, 2, …

Accessing Row Data

Use the column binding name (not header) to access cell values:
// Correct: Use binding name
info.item['severity']     // Binding defined in configuration
info.item['sev']          // Short binding ID
info.item['occ']          // Another binding

// Incorrect: Don't use header text
info.item['Severity']     // ✗ Wrong - this won't work
info.item['Occurrence']   // ✗ Wrong - use binding instead

Return Value Conventions

Formula return values must match the column type:
Column TypeExpected ReturnNotes
intnumberInteger value; RISKSHEET rounds decimals
floatnumberDecimal number with precision preserved
stringstringText value; null renders as empty
dateDate object or stringUse new Date() or YYYY-MM-DD format
booleanbooleantrue or false
enumstringMust match enum option ID, not label
any typenullRepresents empty cell; prevents errors

Null vs Undefined

Always return null for empty values, not undefined:
// Correct: Return null for empty
if (!info.item['severity']) return null;

// Avoid: Undefined may display as "undefined"
if (!info.item['severity']) return;

Operators and Expressions

Formulas support standard JavaScript operators:

Arithmetic Operators

info.item['severity'] * info.item['occurrence']     // Multiplication
info.item['detected'] + info.item['new']            // Addition
info.item['total'] - info.item['resolved']          // Subtraction
info.item['effort'] / info.item['team_size']        // Division
info.item['value'] % 100                            // Modulo (remainder)

Comparison Operators

info.item['severity'] > 3                           // Greater than
info.item['status'] === 'Open'                      // Equality
info.item['priority'] !== 'Low'                     // Inequality
info.item['effort'] >= 5                            // Greater than or equal

Logical Operators

info.item['status'] === 'Open' && info.item['severity'] > 2
info.item['type'] === 'Risk' || info.item['type'] === 'Issue'
!info.item['is_blocked']

Conditional (Ternary) Operator

info.item['status'] === 'Open' ? 100 : 0
info.item['effort'] > 10 ? 'High' : 'Low'

Common Formula Patterns

Safe Access with Fallback

// If severity might be empty, provide default
var severity = info.item['severity'] || 1;
return severity * info.item['occurrence'];

Conditional Calculation

// Only calculate RPN for open risks
if (info.item['status'] === 'closed') {
  return null;
}
return info.item['severity'] * info.item['occurrence'] * info.item['detection'];

Chained Calculations

// Calculate mitigation effectiveness
var originalRpn = info.item['severity'] * info.item['occurrence'] * info.item['detection'];
var mitigatedRpn = info.item['sev_new'] * info.item['occ_new'] * info.item['det_new'];
var reduction = ((originalRpn - mitigatedRpn) / originalRpn) * 100;
return reduction > 0 ? Math.round(reduction) : 0;

String Concatenation

var id = info.item['prefix'] || 'ITEM';
var counter = info.item['sequence'] || '000';
return id + '-' + counter;

Type Conversion

// Convert string to number
var count = parseInt(info.item['item_count'], 10);
return count > 0 ? count : null;

// Convert to boolean
var is_critical = Boolean(info.item['criticality']);
return is_critical ? 'Yes' : 'No';

Formula Configuration in risksheet.json

Inline Formula Definition

Store short formulas directly in the JSON:
{
  "formulas": {
    "rpn": "function(info) { return info.item['sev'] * info.item['occ'] * info.item['det']; }"
  },
  "columns": [
    {
      "header": "RPN",
      "binding": "rpn",
      "type": "int",
      "formula": "rpn"
    }
  ]
}

Top Panel Formula Definition

For complex logic, define formulas in the Top Panel and reference them:
{
  "formulas": {
    "rpn": "(info) => { return getRiskPriority(info); }"
  }
}
Then in the Top Panel <script> section:
<script type="text/javascript">
  function getRiskPriority(info) {
    var severity = info.item['sev'];
    var occurrence = info.item['occ'];
    var detection = info.item['det'];
    
    // Validate inputs
    if (!severity || !occurrence || !detection) {
      return null;
    }
    
    // Calculate RPN
    var rpn = severity * occurrence * detection;
    
    // Return null for zero result (treated as empty)
    return rpn > 0 ? rpn : null;
  }
</script>

Executing Formulas

When Formulas Execute

diagram Formulas that reference changed cells automatically recalculate. Formulas are executed in dependency order when possible.

Formula Execution Context

Formulas execute in the browser, not on the server:
  • Access is immediate (no network latency)
  • Calculations use current grid state
  • All JavaScript features are available (Math, String, Date, etc.)
  • Performance depends on formula complexity and number of rows
For large risksheets (1000+ rows), keep formulas lightweight:
  • Avoid nested loops or recursive logic
  • Pre-calculate constants outside formulas
  • Use simple arithmetic instead of complex functions
  • Consider calculating once during load rather than per-row

Formula Scope and Variables

Formulas are isolated functions with their own scope:
// Each formula execution is independent
// Variables declared inside don't affect other formulas

function(info) {
  var local_var = 10;  // Only exists in this formula
  return local_var * info.item['severity'];
}
To share data between formulas, define functions in the Top Panel:
<script>
  // Shared constants (available to all formulas)
  var SEVERITY_THRESHOLD = 5;
  var CRITICAL_RPN = 200;
  
  // Shared functions
  function isHighRisk(rpn) {
    return rpn >= CRITICAL_RPN;
  }
  
  // Formula can call shared functions
  function(info) {
    var rpn = info.item['sev'] * info.item['occ'] * info.item['det'];
    return isHighRisk(rpn) ? 'Critical' : 'Acceptable';
  }
</script>

Error Handling

Formulas should gracefully handle missing or invalid data:
// Defensive programming: Check before accessing
if (!info.item['severity'] || !info.item['occurrence']) {
  return null;  // Return null for incomplete data
}

var result = info.item['severity'] * info.item['occurrence'];
return result || null;  // Return null if result is 0 or falsy
If a formula throws an error:
  • RISKSHEET displays an error indicator in the cell
  • The error message appears in browser console
  • Other formulas continue executing
  • The cell remains empty until the formula is fixed

Syntax Diagram

Syntax PatternExampleDescription
Function Declarationfunction(info) { ... return value; }Standard function with explicit return
Arrow Function(info) => { ... return value; }Arrow syntax with explicit return
Inline Arrow(info) => expressionConcise single-expression form
Accessing Datainfo.item['columnBinding']Access work item field values
Row/Column Contextinfo.row, info.colAccess row and column metadata
Return ValueMust match column typeReturn null for empty cells

Special Characters in Bindings

If column binding contains special characters, use bracket notation:
// Binding with underscore or hyphen
info.item['column_id']      // Underscore is fine
info.item['column-id']      // Hyphen requires quotes
info.item['column.id']      // Dot requires quotes

// Binding with space (unusual but supported)
info.item['My Column']      // Space requires quotes
Always use bracket notation ['binding'] instead of dot notation for safety. For detailed function library and examples, see Formula Functions and Formula Examples.
KB ArticlesSource Code
  • AppConfig.ts
  • risksheet.json
  • AppConfigHelper.ts
  • CellPreviewFormatter.ts
  • PolarionAppConfigManager.java