Beheben Sie, dass der Zeilenstatushandler in einem Datenfilter-Kontextfeld nicht wie erwartet funktioniertLiebe Community,
Ich versuche, ein Dashboard mit Datenfilterkontext-/Quellenfeldern zu erstellen.
und es funktioniert in einigen Details wie erwartet.
Ich benötige jedoch zusätzliche Funktionen. Basierend auf der Auswahl muss ich eine zusätzliche Tabelle filtern, die sich im Registerkartenfeld Details1 befindet.
Dies erstelle ich jedes Mal neu, indem ich in diesem Kontext „Make Row State Handler“ verwende.
Beim Auswählen einzelner Zeilen in Tabulate ist alles in Ordnung, aber:
- Wenn ich alle abwähle, ändert sich das Registerkartenfeld nicht
- wenn ich in „Tabulieren“ mehr als eine Zeile auswähle, tritt im Registerkartenfeld eine falsche Auswahl auf
- Wenn ich Punkte in GraphBuilder auswähle, wird die Tabellengenerierung übermäßig durchgeführt
- ...
Wie kann dieses Szenario robuster gemacht werden?
Gibt es eine andere Möglichkeit (ohne Zeilenstatus-Handler), die ausgewählten Zeilen in Tabulate und Graph Builder abzurufen?
Gibt es eine bessere Strategie, um solche Dinge zu tun?
Vielen Dank und BR
Names Default To Here( 1 );
Clear Log();
dt = Open( "$SAMPLE_DATA\Big Class.jmp" );
dt << show window( 0 );
tabulate_expr = Expr(
tb_obj = dt << Tabulate( Show Control Panel( 0 ), Add Table( Row Table( Grouping Columns( :sex, :age ) ) ) )
);
gb_expr = Expr(
gb_obj = dt << Graph Builder(
Show Control Panel( 0 ),
Variables( X( :weight ), Y( :height ) ),
Elements( Points( X, Y, Legend( 3 ) ), Smoother( X, Y, Legend( 4 ) ) )
)
);
action_expr = Expr(
Button Box( "Start Analysis", Print( pb_details << get row states() ) )
);
nw = New Window( "Dashboard",
Data Filter Context Box(
H List Box(
V List Box(
H List Box(
Panel Box( "Filter (in Data Filter Source Box)", /* Filter and GB */ dfsb =
Data Filter Source Box( tabulate_expr )
),
Panel Box( "Graph Builder (to be filtered in context", gb_expr )
),
Panel Box( "Action", /* Action */ action_expr )
),
pb_details = Panel Box( "Details (as well in data filter context box)", /* Tab Box */
Tab Box(
Tab Page Box( "Details1 (Data Grid Box, update via Make Row State Handler)", dgb = Data Grid Box() ),
Tab Page Box( "Details2 (Filtered automatically)", tabulate_expr )
)
)
)
)
);
detail_dt = dt << subset( invisible, columns( {"name", "age", "sex"} ) );
dgb << set data table( detail_dt );
dgb << close side panels;
nw << on close(
Close( dt, NoSave );
Close( detail_dt, NoSave );
For Each( {dt}, detail_dt_lst, Try( Close( dt, NoSave ) ) );
);
last_a = []; /* remember last selection to avoid double action */
detail_dt_lst = {}; /* save all table references to be able to close later */
details_update = Function( {a},
If( Is Matrix( a ) & Char( a ) != Char( last_a ),
Show( a );
detail_old = dgb << Get Data Table();
detail_dt = dt << subset( invisible, columns( {"name", "age", "sex"} ) );
Insert Into( detail_dt_lst, detail_dt );
detail_dt << select rows( a ) << delete rows();
dgb << set data table( detail_dt );
dgb << close side panels;
Close( detail_old, NoSave );
last_a = a;
);
);
rsh = pb_details << Make Row State Handler( dt, details_update );
Automatisierung und SkriptingWindowsBetreff: Beheben Sie, dass der Zeilenstatushandler in einem Datenfilter-Kontextfeld nicht wie erwartet funktioniertMeiner Meinung nach gibt es so viele verschiedene Probleme mit Zeilenstatushandlern, dass man sie nicht robust machen kann (zum Beispiel werden sie zu leicht entfernt, lösen zu viele Probleme aus und viele andere). Um einige der Probleme zu vermeiden, die Sie sehen, verwenden Sie nicht den Parameter, den Sie in der Funktion für den Zeilenstatushandler haben können , in Ihrem Fall a , und verwenden Sie stattdessen << Get Selected Rows.
Sie möchten also ein Dashboard mit Tabellen- und Diagrammerstellung haben und diese sollten eine Datentabelle filtern? Ist es notwendig, eine Datentabelle zu haben, die gefiltert wird? Der einfachste Weg, alle Probleme zu vermeiden, besteht darin, ein Schaltflächenfeld zum Aktualisieren der Tabelle zu verwenden.
Betreff: Beheben Sie, dass der Zeilenstatus-Handler in einem Datenfilter-Kontextfeld nicht wie erwartet funktioniertAbhängig von Ihrem tatsächlichen Anwendungsfall gibt es hier eine Option, die funktionieren könnte. Sie basiert auf der Aktualisierung der Teilmenge, anstatt sie neu zu erstellen. Außerdem werden ausgewählte Zeilen überprüft, anstatt sich auf den Parameter „a“ zu verlassen.
Names Default To Here(1);
dt = Open("$SAMPLE_DATA\Big Class.jmp", Invisible);
tabulate_expr = Expr(
tb_obj = dt << Tabulate(
Show Control Panel(0),
Add Table(Row Table(Grouping Columns(:sex, :age)))
)
);
gb_expr = Expr(
gb_obj = dt << Graph Builder(
Show Control Panel(0),
Variables(X(:weight), Y(:height)),
Elements(Points(X, Y, Legend(3)), Smoother(X, Y, Legend(4)))
)
);
action_expr = Expr(
Button Box("Start Analysis", Print(pb_details << get row states()))
);
nw = New Window("Dashboard",
Data Filter Context Box(
H List Box(
V List Box(
H List Box(
Panel Box("Filter (in Data Filter Source Box)",
dfsb = Data Filter Source Box(tabulate_expr)
),
Panel Box("Graph Builder (to be filtered in context",
gb_expr
)
),
Panel Box("Action",
action_expr
)
),
pb_details = Panel Box("Details (as well in data filter context box)",
Tab Box(
Tab Page Box(
"Details1 (Data Grid Box, update via Make Row State Handler)",
dgb = Data Grid Box()
),
Tab Page Box("Details2 (Filtered automatically)",
tabulate_expr
)
)
)
)
)
);
detail_dt = dt << subset(invisible, columns({"name", "age", "sex"}));
dgb << set data table(detail_dt);
dgb << close side panels;
nw << on close(
Close(dt, NoSave);
Close(detail_dt, NoSave);
);
last_rows = {}; // use list as you can compare those directly
extra_triggers = 0;
details_update = Function({a},
// Write("\!N", Round(Tick Seconds(), 2), " \!thappy state handler triggering");
// Show(dt << Get Row States);
cur_rows = As List(dt << Get Selected Rows);
If(N Items(cur_rows) == 0,
cur_rows = As List((1::N Rows(dt))`); // same as all rows selected
);
If(cur_rows == last_rows,
extra_triggers++;
return();
);
Write("\!N", extra_triggers, " unnecessary triggers occured.");
extra_triggers = 0;
last_rows = cur_rows;
If(N Rows(detail_dt) > N Items(cur_rows),
detail_dt << Delete Rows(N Items(cur_rows) + 1::N Rows(detail_dt));
, N Rows(detail_dt) < N Items(cur_rows),
detail_dt << Add Rows(N Items(cur_rows) - N Rows(detail_dt));
);
detail_dt[0, {"name", "age", "sex"}] = dt[Matrix(last_rows), {"name", "age", "sex"}];
);
rsh = pb_details << Make Row State Handler(dt, details_update);
Dies ist zwar nicht die einzige Methode, aber es ist eine recht einfache Option, die Sie ausprobieren können.
Wunschlistenelement in der Hoffnung, dass Statushandler irgendwann verwendbar sein werden: Statushandler von JMP verbessern (Hover-Label, Zeilenstatushandler, Filterstatushandler, Scheduler, …)
Betreff: Beheben Sie, dass der Zeilenstatushandler in einem Datenfilter-Kontextfeld nicht wie erwartet funktioniertEine Quelle der Verwirrung mit < < m> ist, wie das Argument a zu interpretieren ist. Der Vektor stellt die Zeilen dar, die sich geändert haben, sagt aber nichts über ihren Status aus. Sie erhalten auch Rückrufe für Nicht-Filterereignisse – zum Beispiel: Änderungen an Auswahl-, Beschriftungs- oder Markierungszeilenzuständen, die in der Tabelle vorgenommen wurden. Dies macht es schwierig, die Antwort auf die relevanten Ereignisse zu beschränken.
Vor diesem Hintergrund denke ich, dass die Hauptprobleme Ihres ursprünglichen Skripts darin bestehen, dass (1) keine Reaktion erfolgt, wenn die Funktion mehrmals hintereinander mit den gleichen Argumenten aufgerufen wird (deshalb funktioniert „clear“ nicht) und (2) die Zeilennummern als zu löschende Zeilen verwendet werden.
Das folgende Skript (Hinweis: nur JMP 18+) versucht nicht, Änderungen zu verfolgen und zu begrenzen, sollte aber korrekt reagieren und die tatsächlich ausgeschlossenen Zeilen aus der Teilmenge entfernen.
Names Default To Here( 1 );
Clear Log();
//https://community.jmp.com/t5/Discussions/Make-Row-State-Handler-not-working-as-expected-in-a-Data-Filter/m-p/791520
dt = Open( "$SAMPLE_DATA\Big Class.jmp" );
dt << show window( 0 );
tabulate_expr = Expr(
tb_obj = dt << Tabulate( Show Control Panel( 0 ), Add Table( Row Table( Grouping Columns( :sex, :age ) ) ) )
);
gb_expr = Expr(
gb_obj = dt << Graph Builder(
Show Control Panel( 0 ),
Variables( X( :weight ), Y( :height ) ),
Elements( Points( X, Y, Legend( 3 ) ), Smoother( X, Y, Legend( 4 ) ) )
)
);
action_expr = Expr(
Button Box( "Start Analysis", Print( pb_details << get row states() ) )
);
nw = New Window( "Dashboard",
Data Filter Context Box(
H List Box(
V List Box(
H List Box(
Panel Box( "Filter (in Data Filter Source Box)", /* Filter and GB */ dfsb =
Data Filter Source Box( tabulate_expr )
),
Panel Box( "Graph Builder (to be filtered in context", gb_expr )
),
Panel Box( "Action", /* Action */ action_expr )
),
pb_details = Panel Box( "Details (as well in data filter context box)", /* Tab Box */
Tab Box(
Tab Page Box( "Details1 (Data Grid Box, update via Make Row State Handler)", dgb = Data Grid Box() ),
Tab Page Box( "Details2 (Filtered automatically)", tabulate_expr )
)
)
)
)
);
detail_dt = dt << subset( invisible, columns( {"name", "age", "sex"} ) );
dgb << set data table( detail_dt );
dgb << close side panels;
nw << on close(
Close( dt, NoSave );
Close( detail_dt, NoSave );
For Each( {dt}, detail_dt_lst, Try( Close( dt, NoSave ) ) );
);
detail_dt_lst = {}; /* save all table references to be able to close later */
details_update = Function( {a},
Show( a );
If( Is Matrix( a ),
detail_old = dgb << Get Data Table();
detail_dt = dt << subset( invisible, columns( {"name", "age", "sex"} ) );
Insert Into( detail_dt_lst, detail_dt );
filter_state = pb_details << Get Row States(dt);
detail_dt << select rows( Where(Excluded(As Row State(filter_state))) ) << delete rows();
dgb << set data table( detail_dt );
dgb << close side panels;
Close( detail_old, NoSave );
);
);
rsh = pb_details << Make Row State Handler( dt, details_update );
Betreff: Beheben Sie, dass der Zeilenstatus-Handler in einem Datenfilter-Kontextfeld nicht wie erwartet funktioniertDanke für deinen Vorschlag, die Buttonbox wäre eine Lösung.
Ich habe zwei Möglichkeiten:
(1) beim Starten der GUI alle Details zu laden, die ich möglicherweise benötige, sie als versteckte Tabelle beizubehalten und nur den Teil anzuzeigen, den ich in einem bestimmten Kontext benötige. Hier würde ich eine dynamische Lösung mit Rowstate usw. wählen.
(2) auf Anfrage die Daten aus der Datenbank laden (hier würde ich eine Button-Lösung wählen).
Aber der Fall ist für mich grundsätzlich recht interessant, da es viele ähnliche Fälle gibt, bei denen ich (1) oder (2) bevorzugen würde, und ich möchte besser verstehen, wie JMP damit arbeitet.
Betreff: Beheben Sie, dass der Zeilenstatushandler in einem Datenfilter-Kontextfeld nicht wie erwartet funktioniertVielen Dank für Ihre Beiträge @jthi und @danschikore , das gibt mir einige großartige Ideen zur Verbesserung meines Dashboards.