Formule d'initialisation pour nettoyer les erreurs de saisie sur une colonne de référence

J’ai fait une formule d’initialisation pour nettoyer les erreurs de saisie sur une colonne de référence vers une autre table. J’ai testé cette formule sur une colonne de texte, elle règle bien mon problème de retours à la ligne intempestifs. En revanche, quand je la teste sur ma colonne cible (colonne de référence, qui affiche le nom de structures (donc au format texte)), la formule d’initialisation ne nettoie plus le problème des retours à la ligne. Quelqu’un aurait une explication ?

document de test : Document test nettoyage formules - Grist

Si vous avez une formule d’ini sur une colonne de type réf, il vous faudra retourner ["L", value] ou Table.lookupOne(col=value) et non value, sinon le champ ne s’auto-résout pas

plus d’infos ici : Référence insérée via API non reconnue par Grist en tant que telle - #9 par audezu

La formule suivante fonctionne pour remplacer des sauts de lignes dans des valeurs collées dans une colonne de type référence :

val = Simple.lookupOne(nom=str(value).replace("\n"," "))

return val if val else value

avec le str(value) pour transformer en string depuis AltText (le type d’objet d’un champ cassé)

Et

return val if val else value qui permet d’entrer la valeur saisie par l’utilisateurice si jamais la valeur après traitement n’est pas trouvée dans la table de référence

Merci pour les explications !

La formule marche bien pour corriger les erreurs de saisies manuelles dans les cellules, mais lorsque j’utilise des copier-coller depuis excel, la formule ne gère plus le retour à la ligne (les cellules copiées comportent toujours le renvoi à la ligne, et la référence n’est pas reconnue).
Je pensais que j’avais mal identifié les caractères utilisés par excel pour faire le retour à la ligne, mais quand j’utilise la même formule d’initialisation dans une colonne qui n’est pas une colonne de référence, la correction se fait bien.

La formule d’initialisation :

val = Simple.lookupOne(nom=str(value).replace('\r\n',""))

return val if val else value

Est-ce que le fait de copier-coller change l’ordre dans lequel Grist traite les valeurs saisies ?

Bonjour,

Bizarre, la formule fonctionne bien de mon côté, à la fois pour le c/c et pour la saisie dans la cellule, j’ai mis l’exemple ici : https://grist.numerique.gouv.fr/o/docs/aDxjRzs46gVo/Document-test-nettoyage-formules/p/4

Feb-18-2026 10-46-48

Par contre, elle ne prend en compte que le retour à la ligne simple (\n).

Si vous voulez prendre en compte d’autres cas (par ex, un retour à la ligne suivi d’un espace), il faudra adapter la formule. Peut-être que vous pourriez adapter votre grosse formule ?

En remplaçant les value par str(value) ; et en ajoutant à la fin le fait de retourner la valeur de départ, si jamais la valeur corrigée n’existe pas dans la table de référence.

Alors, j’ai fait quelques tests et j’avoue que je m’arrache un peu les cheveux

Voici la formule complète que j’utilise

if not isinstance(value,str):
  return value
# Gestion des espaces insécables (remplacer par des espaces normaux)
value = value.replace('\u00A0', ' ')  # Espace insécable standard
value = value.replace('\u202F', ' ')  # Espace insécable fine
value = value.replace('\u2007', ' ')  # Espace figure
value = value.replace('\u2060', ' ')  # Joiner sans chasse
  
# Gestion des retours à la ligne
value = value.replace('\r\n', '\n')  # Normaliser les fins de ligne
value = value.replace('\r', '\n')    # Convertir les CR en LF
  
# Supprimer les retours à la ligne
value = value.replace('\n', '')
  
# Nettoyage des caractères problématiques
value = value.replace('\t', ' ')     # Remplacer les tabulations par des espaces

# Normaliser les espaces multiples
value = value.strip()
value = re.sub(r"\s+", ' ', value).strip()

val = Simple.lookupOne(nom_ref=value)
return val if val else value

Le détail des opérations de gestion des différents types d’espace n’est pas très important. L’essentiel c’est que cette formule, sur une colonne typée texte, permet de nettoyer les problèmes de copier-coller depuis excel.

En revanche, si j’utilise au début

if not isinstance(value,str):
  return value

alors la formule d’initalisation ne fonctionne pas sur la colonne de référence (i.e, si je copie des cellules depuis excel, les doubles espaces et les retours à la ligne ne sont pas supprimés)

En revanche, si j’utilise ce début :

value = str(value)

Alors dans ce cas seules les cellules sur lesquelles il y avait des erreurs de saisie sont correctement renvoyées comme références. Les autres cellules font figurer en tant que string la référence (par exemple Simple[3], sachant que l’id de ligne 3 correspond bien à la référence qui devrait s’afficher), mais ce string n’est pas reconnu comme référence. Sachant que j’ai essayé de remplacer la fin de la formule par

return val if val else ["L", value]

mais dans ce cas, les cellules concernées affichent seulement « L »

J’ai fait une capture d’écran pour illustrer les résultats que j’obtiens avec les deux versions de la formule

Bonjour, pour gérer les copier/coller depuis d’autres tableurs, cette formule est plus optimale:

# Si dans une autre colonne
" ".join($col.strip().split())
# Même colonne
" ".join(value.strip().split())

Explication:
.strip() : retire toutes les formes d’espace/saut de ligne en début et fin de texte
.split(): sépare chaque la chaîne de caractère. Si aucun « séparateur » n’est précisé, il utilise l’espace (sous toutes ses formes)
" ".join(liste): formate la liste obtenue par le split en chaîne de caractère en utilisant l’espace comme séparateur.

Le fait de strip et split une chaîne de caractères sans préciser de séparateur permet de gérer tous les cas d’espace/saut de lignes d’un seul coup et sans avoir à utiliser du regex !

1 « J'aime »

Bonjour,
Ce n’était pas évident, ceci devrait fonctionner :


value_str = str(value)

# Gestion des espaces insécables (remplacer par des espaces normaux)
value_str = value_str.replace('\u00A0', ' ')  # Espace insécable standard
value_str = value_str.replace('\u202F', ' ')  # Espace insécable fine
value_str = value_str.replace('\u2007', ' ')  # Espace figure
value_str = value_str.replace('\u2060', ' ')  # Joiner sans chasse
  
# Gestion des retours à la ligne
value_str = value_str.replace('\r\n', '\n')  # Normaliser les fins de ligne
value_str = value_str.replace('\r', '\n')    # Convertir les CR en LF
  
# Supprimer les retours à la ligne
value_str = value_str.replace('\n', '')
  
# Nettoyage des caractères problématiques
value_str = value_str.replace('\t', ' ')     # Remplacer les tabulations par des espaces

# Normaliser les espaces multiples
value_str = value_str.strip()
value_str = re.sub(r"\s+", ' ', value_str).strip()

val = Peu_simple.lookupOne(nom_ref=value_str)

return val if val else value

Feb-23-2026 21-03-21

doc d’exemple ici : Document test nettoyage formules - Grist

Ca marche ! :partying_face:

J’avoue que je ne comprends pas trop, parce que j’avais essayé une formule très similaire, qui ne fonctionne pas :

value = str(value)
# Gestion des espaces insécables (remplacer par des espaces normaux)
value = value.replace('\u00A0', ' ')  # Espace insécable standard
value = value.replace('\u202F', ' ')  # Espace insécable fine
value = value.replace('\u2007', ' ')  # Espace figure
value = value.replace('\u2060', ' ')  # Joiner sans chasse
  
# Gestion des retours à la ligne
value = value.replace('\r\n', '\n')  # Normaliser les fins de ligne
value = value.replace('\r', '\n')    # Convertir les CR en LF
  
# Supprimer les retours à la ligne
value = value.replace('\n', '')
  
# Nettoyage des caractères problématiques
value = value.replace('\t', ' ')     # Remplacer les tabulations par des espaces

# Normaliser les espaces multiples
value = value.strip()
value = re.sub(r"\s+", ' ', value).strip()

val = Simple.lookupOne(nom_ref=value)
return val if val else value

La seule différence que j’identifie entre les deux formules, c’est que j’utilise value pour les opérations au lieu d’utiliser un nom pour la variable (value_str dans le cas de la formule qui fonctionne). J’imagine que ce n’est pas très malin d’utiliser value comme nom de variable, mais est-ce que cela explique vraiment la différence de comportement ?

Au-delà de cette question technique, j’ai adapté la formule avec l’excellente suggestion de ythianine (c’est vrai que l’utilisation de regex pour supprimer des espaces, ce n’est pas très élégant). Voici donc le résultat final :

value_str = str(value)

# Gestion des espaces insécables (remplacer par des espaces normaux)
value_str = value_str.replace('\u00A0', ' ')  # Espace insécable standard
value_str = value_str.replace('\u202F', ' ')  # Espace insécable fine
value_str = value_str.replace('\u2007', ' ')  # Espace figure
value_str = value_str.replace('\u2060', ' ')  # Joiner sans chasse
  
# Gestion des retours à la ligne
value_str = value_str.replace('\r\n', '\n')  # Normaliser les fins de ligne
value_str = value_str.replace('\r', '\n')    # Convertir les CR en LF
  
# Supprimer les retours à la ligne
value_str = value_str.replace('\n', '')
  
# Nettoyage des caractères problématiques
value_str = value_str.replace('\t', ' ')     # Remplacer les tabulations par des espaces

# Normaliser les espaces multiples
value_str = " ".join(value_str.strip().split())

val = Simple.lookupOne(nom_ref=value_str)

return val if val else value

La formule conserve probablement des redondances, mais comme cela fonctionne je vais m’en tenir là pour le moment.

Un grand merci pour votre aide ! :heart:

2 « J'aime »

Super :slight_smile:

j’avais fait pareil que vous au début, en réassignant value, le souci c’est qu’à la fin, si la valeur après traitement n’est pas trouvée dans la table référencée, il faut retourner le value initial, qui est de type AltText et non Text (d’où le fait qu’on ait fait str(value) au départ).

Or je ne connais pas de fonction comme altText(value) ?

J’ai donc gardé value intacte et utilisé une autre variable value_str (mais qu’on aurait pu appeler autrement)