Ciao a tutti,
Sto cercando di creare una finestra di dialogo con diverse caselle di riepilogo, ciascuna contenente tutti i valori di una colonna corrispondente in una tabella di dati. Dopo aver selezionato uno o più elementi in uno qualsiasi degli elenchi, desidero filtrare gli elementi negli elenchi rimanenti in base a tale selezione. Ho implementato ciò che ho appena descritto di seguito, ma ecco la cosa: se popolano la finestra di dialogo in un ciclo invece di codificare in modo rigido gli indici del sottoinsieme dell'elenco con numeri interi come di seguito, la funzione viene chiamata con il valore corrente di i al momento di esecuzione invece del valore impiegato quando la casella di riepilogo è stata creata nel ciclo. Ho letto la guida allo scripting e ho provato diverse opzioni tra cui Eval( Eval Expr( Expr())) e Eval Substitute( Expr(), Expr())) ma non riesco a farlo funzionare. Ora devo costruire l'intera espressione come una lunga stringa in un ciclo e Eval( Parse())'ing it ma sembra sciocco. Qualcuno può aiutarmi con la sintassi corretta qui?
Grazie,
Giovanni
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>Grazie ancora. Sembra che rimarrò semplicemente con eval(parse()), anche se sembra un po' come un hack. Ma grazie comunque per i tuoi approfondimenti!
Se è presente il valore i==4, deve esserci una i che non è stata racchiusa in expr().
Parse vs EvalExpr compromessi:
- parse crea stringhe la cui sintassi non è evidenziata nell'editor ma la prossima persona che mantiene il codice probabilmente lo capirà. Nel tuo esempio, potrei inserire eval-parse all'interno del ciclo se potessero esserci centinaia di concatenazioni.
- evalexpr è probabilmente più veloce di parse, ma non fa alcuna differenza per un piccolo esempio. Se stavi costruendo una stringa di un milione di caratteri per concatenazione, potrebbe essere importante. Evaexpr ha bisogno di un commento che dica al prossimo manutentore cosa sta facendo.
Esistono altri approcci alla manipolazione delle espressioni che sono più potenti e più difficili da spiegare e mantenere; Penso che uno di questi sia ragionevole per questo esempio. (arg, narg, head, insertinto, sostituinto, ... Devo impararli di nuovo ogni volta.)
Quello che posso fare è questo, ma sembra che... Sciocco immagino...
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>Grazie per averci provato! Sfortunatamente ho lo stesso problema che avevo riscontrato in passato: quando faccio una selezione nell'elenco, la funzione filterSelected viene chiamata con il valore corrente if i (cioè 4), risultando in un errore di intervallo di pedice.

Prova questo
for( i = 1, i <= N Items( filtercolumns ), i++,
eval(
evalexpr(
filter_boxes << append( Text Box( fq:filtercolumns[Expr( i )], <<SET font="" style=""></SET>Ho usato il caso "1", ho cambiato 1s in expr(i), l'ho messo all'interno di eval/evalexpr, all'interno del ciclo i.
modifica: e domanda ben presentata!