4D Write Pro : les solutions rechercher / remplacer avec les méthodes

Bonjour,

Insistant dès que je peux et la dernière fois aujourd’hui 26/06/19 la tournée 4D de Paris pour que 4D favorise le partage de code lorsqu’il s’agit de résoudre des problèmes comme l’adaptation 4D Write / 4D Write Pro, voici enfin les solutions que je chercher depuis un moment pour rechercher / remplacer dans des zones 4D Write Pro en V17.

Rechercher / remplacer dans le texte brut
Ce que j’avais trouvé en divers endroit de la doc et du forum fonctionnait pour un remplacement de même longueur que la valeur recherchée.
Lorsque les longueurs sont différentes, il faut tenir compte de la différence de longueur et du numéro du remplacement.

https://drive.google.com/open?id=1wU9jMXnYEsuQgm1n81RKyRzqTKwPQuG7La méthode REMPLACEMENT WP TEXTE BRUT est ici>

Rechercher / remplacer dans les expressions 4D
https://drive.google.com/open?id=11Bx0hAekw_BgodeXe2ORRHWAQJmPpYkgLa méthode REMPLACEMENT WP EXPRESSIONS 4D est ici>

J’espère que je ne serai pas le seul à partager des méthodes utiles pour ce sujet qui freine la migration chez pas mal de clients et que 4D mettra en place des espaces et procédures simples pour rendre plus visible sur sur le forum ces partages.

Il y a quelques jours Gabriel a publié un article sur la fonction rechercher / Remplacer avec 4D Write Pro sur son BLOG.

Voici le lien :

:fr: https://www.my4dexperience.com/post/tip-7-4d-write-pro-chercher-remplacer

:us: https://www.my4dexperience.com/post/tip-7-4d-write-pro-find-replace

mes deux chocs :slight_smile:

Bonjour,

J’avais vu et construit une méthode générique avec le principe de ton post que j’avais étudié, mais chez moi ça ne fonctionnait pas dans les cas de longueurs différentes entre le morceau recherché et à remplacer et il fallait réécrire une méthode générique.

Je n’ai pas d’action sur la façon de faire, mais là, on peut avoir les méthodes génériques déjà construites et directement utilisables, ce que je n’avais pas trouvé après de longs moments de recherches et tests…

Merci à toi car ça a participé à m’orienter progressivement vers la méthode finale.

Je ne suis que le messager :wink:

C’est Gabriel qui a écrit ce code.

En tout cas ravi que ça a pu t’aider !

Bonjour,

J’avais eu ce problème dans mon premier test, car je remplaçais les occurrences de 1 à X.

Si tu as bien regardé mon code, je commence à la dernière position et je descends (de X à 1). Cela évite d’avoir à gérer les longueurs différentes.

Je ne sais pas si cela peut s’appliquer à ton cas.

Merci en tout les cas du partage.

Pour ceux qui veulent voir la méthode de Michel sans la télécharger puis l’importer, la voici légèrement modifiée. J’ai retiré l’affectation dans un champ 4D en ne laissant que le traitement de remplacement.

<code 4D>
// WPRO_remplaceTexte (->zonePro ; “ancien” ; “nouveau” ) -> nombre de remplacements ( -1 si texte inexistant )
// remplace un morceau de texte par un autre dans une zone write pro
// NOTE : le texte dans les expressions n’est PAS remplacé
// par Michel Troya avec l’aide de Roland Lannuzel de 4D
// voir aussi : WPRO_remplaceExpression

C_ENTIER LONG($0;$longueur;$debutAncien)
C_POINTEUR($1)
C_TEXTE($2;$3)
C_OBJET($objetWrite;$plage)

$0:=Aucun enregistrement courant // convention pour dire que l’objet n’est pas défini par défaut

Si (OB Est défini($1->))

$objetWrite:=Créer objet
$objetWrite:=OB Copier($1->)

$ancien:=$2
$nouveau:=$3
$longueur:=Longueur($ancien)
$difference:=Longueur($nouveau)-Longueur($ancien)

$texteSansExpressions:=WP Lire texte($objetWrite;wk expressions as space)  // texte brut de la zone write SANS les expressions
$position:=0  // début du texte
$n:=0  // compte le nombre de remplacements effectués

Repeter 
	
	$position:=Position($ancien;$texteSansExpressions;$position+1)
	
	Si ($position>0)  // cible trouvée
		
		$n:=$n+1
		$debutAncien:=($n-1)*$difference+$position  // à chaque remplacement, on doit se décaler de la différence de longueur entre 'ancien' et 'nouveau'
		$plage:=WP Créer plage($objetWrite;$debutAncien;$debutAncien+$longueur)  // on isole la cible (ancien mot) dans une plage
		WP FIXER TEXTE($plage;$nouveau;wk replace)  // 'ancien' remplacé par 'nouveau'
		
	Fin de si 
	
Jusque ($position<=0)

Si ($n>0)  // zone modifiée
	$1->:=$objetWrite
Fin de si 

$0:=$n

Fin de si

</code 4D>

Idem pour la méthode traitant des expressions :

<code 4D>
// WPRO_remplaceExpression ( ->zonePro ; “ancien” ; “nouveau” ) -> nombre de remplacements
// remplace un morceau d’expression par un autre dans une zone write pro : WPRO_remplaceExpression (->[table]writepro;"#,#";"#.#")
// par michel Troya
// d’après forum 4D Roland Lanuzel https://forums.4d.com/Post/FR/29819796/1/29822625#29822625
// voir aussi : WPRO_remplaceTexte

C_POINTEUR($1)
C_OBJET($objetWrite)
C_ENTIER LONG($0;$curseur;$decalage;$longueurTexte;$longueurExpression)
C_TEXTE($2;$3;$texteSansExpressions;$texteAvecExpressions;$expression;$ancien;$nouveau)

$0:=Aucun enregistrement courant

Si (OB Est défini($1->))

$objetWrite:=Créer objet
$objetWrite:=OB Copier($1->)

$ancien:=$2
$nouveau:=$3

$texteAvecExpressions:=WP Lire texte($1->;wk expressions as source)  // transforme la zone Pro en texte en conservant le texte des expressions 4D
$texteSansExpressions:=WP Lire texte($1->;wk expressions as space)  // transforme zone Pro en texte en remplaçant les expressions 4D par des espaces (permettra l'insertion de la nouvelle expression au bon endroit)

$longueurTexte:=Longueur($texteSansExpressions)
$decalage:=0
$n:=0  // compte le nombre de remplacements effectués

Boucle ($curseur;1;$longueurTexte)
	
	$decalage:=$decalage+1
	
	Si ($texteSansExpressions[$curseur]#$texteAvecExpressions[$curseur])  // différence entre les deux versions du texte
		
		$expression:=ST Lire expression($objetWrite;$curseur;$curseur)
		
		Si ($expression#"")  // c'est bien une expression
			
			$longueurExpression:=Longueur($expression)
			$expression:=Remplacer chaîne($expression;$ancien;$nouveau)  // remplacement dans l'expression 4D
			$n:=$n+1
			
			ST INSÉRER EXPRESSION($objetWrite;$expression;$curseur;$curseur+1)  // remplacement dans le texte source
			$decalage:=$decalage+$longueurExpression-1  // ajoute la longueur de l'expression source avant la prochaine boucle 
			
		Fin de si 
	Fin de si 
	
Fin de boucle 

Si ($n>0)  // zone modifiée
	$1->:=$objetWrite
Fin de si 

$0:=$n

Fin de si

</code 4D>

bonjour

juste une remarque
À la lecture (rapide) du code, je comprends que vous passez un pointeur sur un objet 4DWP, c’est bien ça ?

Si c’est bien ça, c’est totalement inutile.

Les objets sont passés en tant que références, pas en tant que valeur; L’étape de pointage/dépointage peut (devrait !) donc être supprimée.

Roland

Bonjour Roland,

Pour vérifier que j’ai compris à quoi tu fais allusion :

J’utilise un pointeur vers la zone WP pour que ce soit générique, tu veux dire que je pourrai mettre un $1 C_OBJET au lieu de C_POINTEUR et passer directement la zone WP au lieu de le mettre en pointeur, c’est ça ?

Absolument.

Les objets (en général, pas seulement les objets 4DWP) sont toujours passés comme des références aux méthodes (sauf si la méthode à l’attribut “execute on server”, là 4D n’a pas d’autre moyen que de passer une valeur, càd l’objet complet. Ce qui se comprend, vous ne pourriez non plus passer un pointeur dans ce cas)

Roland

J’ai commencé à basculer en v17 et writePro était le plus urgent. J’ai enlevé tous les pointeurs sur les objets write pour partir sur de bonnes bases. Merci

Bonjour Hervé.

J’insiste : il ne s’agit pas que des objets 4DWP, mais de tous les objets en général !

MaMethode (->monObjet) marche (à condition de dépointer à l’arrivée bien sûr) mais ça n’a pas de sens. Un pointeur sur un objet c’est une référence sur une référence.

Je ne vais pas faire une formation ici, mais les objets sont (presque) toujours passés en référénce, PAS en valeur.

Presque ?
Seules exceptions (j’espère ne pas en ounblier) :

  • quand la méthode s’execute sur le serveur (ben oui, y’a pas de magie, là 4D doit bien copier l’objet)
  • Quand on passe un objet (non partagé !) à “New process” ou a “Call worker”
    (et oui, si il est partagé, c’est AUSSI sa référence qui est envoyée.)

C’est la même chose avec une affectation de “variable”
a:=new object()
b:=a
c:=b

a, b et c sont des références au MÊME objet, l’objet lui-même n’est PAS dupliqué :slight_smile:


HTH

Cordialement,

Roland

Le fait de tout remplacer m’a montré un cas étrange pour la commande :

OBJET FIXER CORRECTION ORTHOGRAPHIQUE

Cela marche pour un objet write indiqué par son nom :

OBJET FIXER CORRECTION ORTHOGRAPHIQUE($*;“zoneWritePro”;<>CorrectionOrthographe)

mais 4D retourne une erreur si on met directement la zone :

OBJET FIXER CORRECTION ORTHOGRAPHIQUE(zoneWritePro;<>CorrectionOrthographe)

alors que cela fonctionnait avec un pointeur vers la zone.

je suis la release 17r4

Bonjour Hervé,

Pour toutes les commandes qui traitent les objets formulaires, il est (très) conseillé de passer par les noms des objets formulaires ce qui ôte toute confusion puisque les noms sont uniques.
Quand on passe une variable, c’est la “première” variable trouvée à qui s’applique la commande.
(il peut y avoir plusieurs instances d’une même variable dans un formulaire)
Idem pour un pointeur dépointé.

Bon, cela dit, cette commande devrait faire pareil (selon la doc) donc je vous suggère de saisir un bug :slight_smile:

Cordialement

Roland Lannuzel