Skip to content

Conversation

@Meklo
Copy link
Contributor

@Meklo Meklo commented Nov 5, 2025

PR Summary

New Features

  • Added ErrorCellRenderer component to display #ERROR for invalid formula results, with localized tooltip messages.
  • Updated math.ts to return structured validation errors instead of throwing exceptions.
  • Added new translation keys for formula related errors in spreadsheet-en.ts and spreadsheet-fr.ts.

Behavior Changes

  • column-mapper.ts:
    • Uses ErrorCellRenderer when a formula result is invalid.
    • Uses isValidationResult to determine cell rendering behavior through AG grid cellRendererSelector prop
  • Typing validation errors (e.g., wrong data type returned by a formula) are now displayed in cells alongside forbidden math.js function errors.
    When both occur, forbidden math.js errors take priority (can be changed).

Other

  • Disabled math.js functions (import, parse, simplify, etc.) now return validation errors instead of exceptions.
  • Added corresponding error message translations.

Going Further

This system can be incremented on to handle more math.js resolution errors by tweaking the createValueGetter function.
In particular, additional error thrown during formula evaluation can be caught in its catch block and returned as a ValidationResult. This would allow the ErrorCellRenderer to display consistent error feedback for a wider range of math.js errors.

Additionnaly the ErrorCellRenderer could be specialized to display a diferent code depending on the type of caught error

Copy link
Contributor

@dbraquart dbraquart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code : a few remarks
tests: ok

return validation;
}
return result;
} catch (e) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we could manage any "evaluate" error from MathJS in this catch. Next step ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Precisely :) I elaborated on this in the going further section or the summary

@Meklo Meklo requested a review from dbraquart November 13, 2025 09:52
@sonarqubecloud
Copy link

Copy link
Contributor

@TheMaskedTurtle TheMaskedTurtle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it can be simplified a lot. Think about it like the evaluation either returns a value or a ValidationError. In the end for each column definition, is it is a value we take DefaultCellRenderer and if it is a ValidationError we take ErrorCellRenderer.

import { SortParams } from '../hooks/use-custom-aggrid-sort';
import { COLUMN_TYPES, CustomCellType } from '../custom-aggrid-header.type';
import type { UUID } from 'node:crypto';
import { ValidationResult } from '../../spreadsheet-view/columns/utils/formula-validator';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import type

import { ICellRendererParams } from 'ag-grid-community';
import { CustomCellRendererProps } from 'ag-grid-react';
import { mergeSx, type MuiStyles } from '@gridsuite/commons-ui';
import { IntlShape } from 'react-intl';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import type

}

export const formatValidationResult = (isValid: boolean, messageId?: string): ValidationResult => {
return { isValid: isValid, error: messageId };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return { isValid: isValid, error: messageId };
return { isValid, error: messageId };

return isValidationResult(value) && !value.isValid;
}

export const formatValidationResult = (isValid: boolean, messageId?: string): ValidationResult => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not really helpful

);

export const ErrorCellRenderer = (props: ErrorCellRendererParams) => {
const errorMessage = props.intl.formatMessage({ id: props.value?.error });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are in react context here already, you can use useIntl directly you don't need to pass it through props

};
});

const addFormulaErrorsRenderer = (intl: IntlShape, columns: CustomColDef[]): CustomColDef[] => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you add it in mapColumns directly ?

import { IntlShape, useIntl } from 'react-intl';
import { useMemo } from 'react';

export const useColumnDefinitions = (tableDefinition: SpreadsheetTabDefinition) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is not useful

import { MAX_FORMULA_CHARACTERS } from '../../constants';

interface ValidationResult {
export interface ValidationResult {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe name it ValidationError directly with
{
error: string;
}

};

export const validateFormulaResult = (value: any, type: COLUMN_TYPES): ValidationResult => {
if (isValidationResult(value)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this method it could be, if check passes returns the orginal value, if not returns a ValidationError

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants