Hallo zusammen,
Ich versuche, ein Dialogfenster mit mehreren Listenfeldern zu erstellen, die jeweils alle Werte einer entsprechenden Spalte in einer Datentabelle enthalten. Bei der Auswahl eines oder mehrerer Elemente in einer der Listen möchte ich, dass die Elemente in den verbleibenden Listen entsprechend dieser Auswahl gefiltert werden. Ich habe implementiert, was ich gerade unten beschrieben habe, aber hier ist die Sache: Wenn ich das Dialogfenster in einer Schleife fülle, anstatt die Listenteilmengenindizes wie unten hart mit Ganzzahlen zu codieren, wird die Funktion mit dem aktuellen Wert von i zum Zeitpunkt von aufgerufen Ausführung anstelle des Werts, der beim Erstellen der Listbox in der Schleife verwendet wurde. Ich habe den Skriptleitfaden durchgelesen und verschiedene Optionen ausprobiert, darunter Eval( Eval Expr( Expr())) und Eval Substitute( Expr(), Expr())), aber ich bekomme es nicht zum Laufen. Ich muss jetzt den gesamten Ausdruck als lange Zeichenfolge in einer Schleife erstellen und ihn auswerten (Parse()), aber das kommt mir einfach albern vor. Kann mir hier jemand mit der richtigen Syntax helfen?
Danke,
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>Danke noch einmal. Ich sehe so aus, als würde ich dann einfach bei eval(parse()) bleiben, auch wenn es ein bisschen wie ein Hack wirkt. Aber trotzdem vielen Dank für eure Einblicke!
Wenn der Wert i==4 vorhanden ist, muss es ein i geben, das nicht in expr() eingeschlossen wurde.
Kompromisse zwischen Parse und EvalExpr:
- parse erstellt Zeichenfolgen, deren Syntax im Editor nicht hervorgehoben wird, die aber von der nächsten Person, die den Code verwaltet, wahrscheinlich verstanden werden. In Ihrem Beispiel könnte ich die Auswertungsanalyse in die Schleife einfügen, wenn es Hunderte von Verkettungen geben könnte.
- evalexpr ist wahrscheinlich schneller als parse, macht aber für ein kleines Beispiel keinen wirklichen Unterschied. Wenn Sie eine Zeichenfolge mit einer Million Zeichen durch Verkettung erstellen, könnte dies wichtig sein. Evalexpr benötigt einen Kommentar, der dem nächsten Betreuer mitteilt, was es tut.
Es gibt andere Ansätze zur Manipulation von Ausdrücken, die leistungsfähiger und schwieriger zu erklären und aufrechtzuerhalten sind; Ich denke, dass beides für dieses Beispiel angemessen ist. (arg, narg, head, insertinto, replacementinto, ... Ich muss diese jedes Mal neu lernen.)
Was ich tun kann, ist Folgendes, aber das scheint einfach... Blöd, denke ich...
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>Vielen Dank, dass Sie es versucht haben! Leider habe ich das gleiche Problem wie in der Vergangenheit: Wenn ich eine Auswahl in der Liste treffe, wird die filterSelected-Funktion mit dem aktuellen Wert von i (also 4) aufgerufen, was zu einem Subscript Range-Fehler führt.

Versuche dies
for( i = 1, i <= N Items( filtercolumns ), i++,
eval(
evalexpr(
filter_boxes << append( Text Box( fq:filtercolumns[Expr( i )], <<SET font="" style=""></SET>Ich habe den Fall „1“ verwendet, die Einsen in expr(i) geändert und das in eval/evalexpr, in die i-Schleife eingefügt.
edit: und schön gestellte Frage!