Salut tout le monde,
J'essaie de créer une fenêtre de dialogue avec plusieurs zones de liste, chacune contenant toutes les valeurs d'une colonne correspondante dans une table de données. Lors de la sélection d'un ou plusieurs éléments dans l'une des listes, je souhaite que les éléments des listes restantes soient filtrés en fonction de cette sélection. J'ai implémenté ce que je viens de décrire ci-dessous, mais voici le problème : si je remplis la fenêtre de dialogue dans une boucle au lieu de coder en dur les index des sous-ensembles de liste avec des entiers comme ci-dessous, la fonction est appelée avec la valeur actuelle de i au moment de exécution au lieu de la valeur prise lors de la création de la listbox dans la boucle. J'ai lu le guide de script et essayé plusieurs options, notamment Eval( Eval Expr(Expr())) et Eval Substitute(Expr(), Expr())) mais je n'arrive pas à le faire fonctionner. Je suis maintenant en train de construire l'expression entière sous la forme d'une longue chaîne dans une boucle et de l'évaluer (Parse()) mais cela semble tout simplement idiot. Quelqu'un peut-il m'aider avec la syntaxe appropriée ici ?
Merci,
Johan
Names Default To Here( 1 );
If( !Namespace Exists( "fq" ),
New Namespace(
"fq"
)
);
dt = New Table( "Sample data",
Add Rows( 9 ),
New Column( "id",
Character,
"Nominal",
Set Values( {"a", "a", "a", "b", "b", "b", "c", "c", "c"} )
),
New Column( "value",
Character,
"Nominal",
Set Values( {"A", "B", "C", "D", "E", "F", "G", "H", "I"} )
),
New Column( "val2",
Character,
"Nominal",
Set Values( {"one", "two", "three", "one", "two", "three","one", "two", "three"} )
)
);
filterSelected = Function( {dt, values, index},
/*
Sorts displayed values in all list boxes based on selection
*/
columns = fq:filterColumns;
filters = fq:filters;
selectedColum = Remove From( columns, index )[1];
selctedFilter = Remove From( filters, index )[1];
rows = dt << Get rows where( Contains( values, as Column( dt, selectedColum ) ) );
// If nothing is selcted, all values should be chosen
If(Length(values)==0,
rows = dt << get rows where(!Ismissing(As Column(dt, selectedColum)))
);
// Set list items according to selection
Local( {j = 1},
For( j = 1, j <= N Items( filters ), j++,
filters[j] << Set items( Column( dt, columns[j] )[rows] )
)
);
);
getSelection = Function( {},
Local( {j =1},
For( j=1, j <= N Items(fq:filters), j++,
print(fq:filterColumns[j], fq:filters[j] << get items());
);
);
);
nestedFilters = Function( {filtercolumns},
fq:filtercolumns = filtercolumns;
dialog = New Window( "Fetch rows matching:",
Show Menu( 0 ),
show toolbars( 0 ),
Border Box( Top( 20 ), Bottom( 20 ), Left( 10 ), Right( 10 ),
V List Box(
Align( right ),
filter_boxes = V List Box(),
H List Box(
ok_button = Button Box( "OK" ),
cancel_button = Button Box( "Cancel", dialog << close window )
)
)
),
ok_button << Set function(
getSelection();
dialog << close window;
)
);
fq:filters = {};
fq:all_rows = {};
//for(i=1, i<=N Items(filtercolumns), i++,
filter_boxes << append( Text Box( fq:filtercolumns[1], <<SET font="" style=""></SET>Merci encore. On dirait que je vais m'en tenir à eval(parse()) alors, même si cela ressemble un peu à un hack. Mais merci quand même pour vos idées !
Si la valeur i==4 est présente, il doit y avoir un i qui n'a pas été enveloppé dans expr().
Compromis entre Parse et EvalExpr :
- parse crée des chaînes dont la syntaxe n'est pas mise en évidence dans l'éditeur, mais la prochaine personne qui gère le code le comprendra probablement. Dans votre exemple, je pourrais mettre l'analyse eval dans la boucle s'il pouvait y avoir des centaines de concaténations.
- evalexpr est probablement plus rapide que parse, mais ne fait aucune différence réelle pour un petit exemple. Si vous construisiez une chaîne d'un million de caractères par concaténation, cela pourrait être important. Evalexpr a besoin d'un commentaire indiquant au prochain responsable ce qu'il fait.
Il existe d’autres approches pour manipuler les expressions, plus puissantes et plus difficiles à expliquer et à maintenir ; Je pense que l'un ou l'autre de ces éléments est raisonnable pour cet exemple. (arg, narg, head, insertinto, substitutinto, ... Je dois les réapprendre à chaque fois.)
Ce que je peux faire, c'est ceci, mais cela semble juste... C'est idiot, je suppose...
expression = "";
for( i = 1, i <= N Items( fq:filtercolumns ), i++,
expression = expression ||
"filter_boxes << append( Text Box( fq:filtercolumns[" || char(i) || "], <<SET font="" style=""></SET>Merci d'avoir essayé ! Malheureusement, je rencontre le même problème que dans le passé : lorsque j'effectue une sélection dans la liste, la fonction filterSelected est appelée avec la valeur actuelle si i (c'est-à-dire 4), ce qui entraîne une erreur de plage d'indice.

Essaye ça
for( i = 1, i <= N Items( filtercolumns ), i++,
eval(
evalexpr(
filter_boxes << append( Text Box( fq:filtercolumns[Expr( i )], <<SET font="" style=""></SET>J'ai utilisé le cas "1", j'ai changé les 1 en expr(i), je l'ai mis dans le eval/evalexpr, dans la boucle i.
edit : et question bien présentée !