Obtenir un pointeur (ou variable) champs à partir d'une chaine de caractère

Product :4D - 4D Server
V17.3
OS : Windows
Comment passer d’une variable alphanumérique : NomChamps:="[A]Nom"
à une variable de type Champs ou un pointeur Champs : Champs ou ->Champs ?

Un des usages :
Pour une programmation générique de tri (sans passer de tableaux de pointeurs Table et/ou Champs),
Dans un formulaire liste de table [A]
Un Objet de Type Bouton invisible en entête de colonne (aillant en propriété, pour nom le nom du champs à trier)
En méthode objet, (sur clic) :
NomChamps := OBJET Lire champs // On récupère une chaine alpha du Nom du Champs à Trier
Champs:= ?? // Code manquant pour traduire la chaine en variable Champs
ou
Champs->:= ?? // Code manquant pour traduire la chaine en pointeur Champs
Pour faire ensuite des tris :
Trier(NomChamps;>) ou Trier(->Champs;>)…

Il faut une fonction de conversion de nom de table et de champ en pointeurs, comme https://forums.4d.com/Post/FR/12642078/2/19520732#19520732ici>.

Ceci posé, comme il s’agit d’un formulaire liste : la colonne qui est au-dessous du bouton invisible, elle n’affiche pas toujours le même champ ?

Oui, bien vu, merci

J’ai adapté la boucle finale de cette fonction :
$NomChamp:=OBJET Lire nom // N.B. Le nom de variable du bouton invisible contient le nom du champ à trier
$ITable:=Table(Table du formulaire courant) // N° Table courante
Si (Est un numéro de table valide($ITable))
Boucle ($IChamp;1;Lire numéro dernier champ($ITable))
Si (Est un numéro de champ valide($ITable;$IChamp)) //Le champ existe et est valide
$Pt1:=Champ($ITable;$IChamp)
Fin de si
Fin de boucle
Fin de si

Si on travaille sur un formulaire et qu’on veut un pointeur sur un champ:

Une alternative :

<code 4D>
// Méthode lire pointeur par le nom

C_POINTER($0;$P_Pointeur)

C_TEXT($1;$T_Object)
$T_Object:=$1
FORM GET OBJECTS($rT_Nom;$rP_Pointer)
$L_Pos:=Find in array($rT_Nom;$T_Object)
If ($L_Pos>-1)
$P_Pointeur:=$rP_Pointer{$L_Pos}
End if

$0:=$P_Pointeur
</code 4D>

<code 4D>
$Pointeur:=lire pointeur par le nom(“nom champ”)
</code 4D>

Il manquait le test dans mon code… :

$NomChamp:=OBJET Lire nom // N.B. Le nom de variable du bouton invisible contient le nom du champ à trier
$ITable:=Table(Table du formulaire courant)
Si (Est un numéro de table valide($ITable))
Boucle ($IChamp;1;Lire numéro dernier champ($ITable))
Si (Est un numéro de champ valide($ITable;$IChamp))
Si(Nom du champ($ITable;$IChamp)=$NomChamp)
$Pt1:=Champ($ITable;$IChamp)
Fin de si
Fin de si
Fin de boucle
Fin de si

Merci pour l’idée

Oui, peut être plus rapide ?

Humm
$Pointeur:=lire pointeur par le nom(“nom champ”) me revoie : ->$form_24_26
non exploitable pour Trier($Pointeur->;<) ??

you could use Parse formula with tokens to obtain the table number and field number.

then Match regex to extract the values and pass them to Field.

Donner le nom du champ au bouton est une très mauvaise idée…
Si la base contient plusieurs champs de même nom, et ça arrive souvent, ça va devenir compliqué.
A moins de coller le numéro de la table devant ou derrière, et de décomposer la chaine alpha pour utiliser la fonction Champ ensuite.
Mais de toutes façons, ce n’est pas une vraie générique, puisque l’objet qui la porte doit être correctement nommé.
Pourquoi ne pas tout simplement utiliser TRIER(Champ) ?

: Antoine GALMICHE

Pourquoi ne pas tout simplement utiliser TRIER(Champ) ?
Exactement, c’était le sens de ma question, au début.

S’il s’agit comme je l’ai compris d’une liste “classique”, ça se construit “en dur”. Vouloir “génériquer” ce qui ne l’est pas est du temps perdu, sera lent à exécuter, le champ sera introuvable par la recherche dans le code, les effets de bord potentiels existent, etc.

J’ai ces routines de conversion “nom vers pointeur” depuis très longtemps, je pense que la plupart des développeurs ont les leurs depuis longtemps également. En ce qui me concerne elles m’ont fort peu servi dans le passé, aujourd’hui l’asymptote tend vers keudal.

Je pense qu’il sera beaucoup plus intéressant (et gratifiant) de remplacer cette liste par une listbox.

: Arnaud DE MONTARD
: Antoine GALMICHE
.../...

Je pense qu’il sera beaucoup plus intéressant (et gratifiant) de remplacer cette liste par une listbox.

Oui on commence par ça et ensuite le souci du tri ne sera plus un souci sans tous ces trucs de pointeur dépointés et d’alphanumérique à parser et je ne sais quoi.

Précision sur l’objet initial du besoin :

Avoir un (modèle de) bouton invisible de tri à placer en entête de colonne à la création des formulaires liste
Ce (modèle de) bouton ayant en évènement le clic coché et en méthode une ligne de code appelant une méthode projet permettant des tris (>;<) et accessoirement des couleurs, du gras,…

En même temps qu’on place ces boutons sur un nouveau formulaire liste, on adapte leur dimension à chacune des colonnes du formulaire dans la liste des propriétés et on nomme les boutons du nom du champ à trier. Rapide…

La méthode d’Arnaud de Montard DB_fieldPtrByName retourne un pointeur de champs utilisable directement
La méthode de Bertrand Soubeyrand lire pointeur par le nom retourne un pointeur d’objet sous forme $form_D_17 et il reste à trouver le pointeur champ correspondant : Comment ?

Pas compris la remarque d’Arnaud de Montard : remplacer cette liste par une listbox ?

Alors si tu tiens absolument à une générique, donc à une méthode qui n’aura pas à être modifiée quand tu la copieras d’un bouton à l’autre, tu n’as pas (à ma connaissance) d’autre moyen que de nommer tes boutons suivant une règle qui indique la table et le champ.
Par exemple bTTTCCC avec TTT format sur 000 du n° de table et pareil pour CCC.
Puis dans la méthode, tu décomposes la chaine par sous-chaine et tu exécutes le tri via TRIER(Champ(T,C)->)

Arnaud a tout à fait raison, comme d’habitude :-), une listbox résoudrait d’une façon absolue ton problème, le tri pouvant être géré en interne.

On peut éviter de coder TTT pour la table car la méthode récupère son pointeur facilement :
$ITable:=Table(Table du formulaire courant) // Table renvoie un pointeur à partir du N° Table courante

: Dr VALLEE CUSSAC VIVIANNE

La méthode de Bertrand Soubeyrand lire pointeur par le nom retourne
un pointeur d’objet sous forme $form_D_17 et il reste à trouver le
pointeur champ correspondant : Comment ?

Voila:
<code 4D>
If ($Pointeur#Null) // on ne sait jamais !

$nom:=Field name($Pointeur)
$Valeur_du champ:=$Pointeur->
$type:=Type($Pointeur->)

end if
</code 4D>

Rectif :
On peut éviter de coder TTT pour la table car la méthode récupère son N° facilement :
$ITable:=Table(Table du formulaire courant) // Table renvoie un N° à partir du pointeur de Table courante

: Antoine GALMICHE

Arnaud a tout à fait raison, comme d’habitude :-).
Normalement les énormités et autres second degrés, c’est que le vendredi. Y’a dérogation pendant le confinement ?

: Dr VALLEE CUSSAC VIVIANNE

Pas compris la remarque d’Arnaud de Montard : remplacer cette liste
par une listbox ?
J’imagine que la liste dont tu parles est un formulaire de sortie, que tu utilises avec MODIFIER SELECTION ou VISUALISER SELECTION : c’est cela ? Si oui, ces “anciennes” listes peuvent (et même devraient…) être remplacées par des listbox selection, avec tout un tas de bénéfices à la clé.

Pour n’en citer qu’un, dans la liste à l’ancienne, bouton et colonne au dessous sont deux objets sans lien aucun, seul le code dit au bouton quoi trier. Dans une listbox sélection, il n’y a rien à programmer pour le tri : le bouton fait partie de la listbox et sait faire les tris croissant et décroissant sur la colonne à laquelle il est associé.

Si c’est nouveau pour toi, on s’emmerde tous tellement que tu trouveras sûrement de l’aide si ça te dit de t’y lancer :wink:

Merci pour vos contributions,
Effectivement mettre le N° de champ en nom du bouton invisible simplifie la méthode appelée :

$ITable:=Table(Table du formulaire courant) // Table renvoie un pointeur à partir du N° Table courante
$IChamp:=Num(OBJET Lire nom) // N° champ à trier en format alphanum
Si (Est un numéro de table valide($ITable)) //La Table existe et est valide
Si (Est un numéro de champ valide($ITable;$IChamp)) //Le Champ existe et est valide
$Pt1:=Champ($ITable;$IChamp) // Pointeur du champ à trier
Fin de si
Fin de si

Avant de clore ce fil juste une question pour ma culture G :
Comment obtenir le pointeur de Champ correspondant au pointeur d’objet (de type Champ) d’un formulaire (ex: ->$form_38_49) ?

: Dr VALLEE CUSSAC VIVIANNE

Oui, peut être plus rapide ?
Certainement pas : si on utilise une indirection (un pointeur en est une), c’est forcément un “étage” supplémentaire.