2022_Q1 MakeOverChallenge: Aktion per Mausklick auf verschiedene ArtenDies ist die Makeover Challenge Q1 2022.
Das Ziel besteht darin, ein Beispiel, ein Skript oder eine Anleitung zu entwickeln, um eine der drei Aufgaben zu erfüllen (alle haben damit zu tun, eine Aktion auszulösen, nachdem Sie in JMP auf etwas geklickt haben):
- Herausforderung A: (Bilder und Skript zum Erstellen einer ersten Datentabelle zum Öffnen der beigefügten Bilder: 2022Q1_ChallengeA.zip)
- Sie haben: Eine Datentabellenspalte mit Bildern oder Links zu einer Website oder einer Datei (auch Ausdrücke genannt)
- Sie möchten: auf eine Zelle dieser Spalte klicken und den Link oder das Bild außerhalb von JMP öffnen
- Das übergeordnete Ziel: Durch Klicken in eine Datentabellenzelle sollte etwas ausgelöst werden
- Herausforderung B : (Skript zum Öffnen der Datentabelle und zum Erstellen des beigefügten Berichts: 2022Q1_ChallengeB_starterScript.jsl)
- Sie haben: Big Class und einen Graph Builder-Bericht über Gewicht nach Größe (siehe Skript)
- Sie möchten: Durch das Schließen des Graph Builder-Berichts sollte ein Verteilungsbericht „Alter“ geöffnet werden. Speichern Sie diesen Bericht als Bild und schließen Sie den Verteilungsbericht.
- Das übergeordnete Ziel: Das Schließen eines Fensters soll eine Aktion auslösen
- Herausforderung C: (Skript zum Öffnen der Datentabelle und zum Erstellen des beigefügten Berichts: 2022Q1_ChallengeC_starterScript.jsl)
- Sie haben: Einen Graph Builder-Bericht zu Beispieldaten für Wachstumsmessungen.
- Sie möchten: Wenn Sie auf eine Zeile klicken oder mehrere Zeilen (oder Kategorien in der Legende) auswählen, möchten Sie eine Teilmenge der ausgewählten Zeilen generieren.
- Das übergeordnete Ziel: Ein Klick auf eine Grafik oder einen Bericht sollte eine Aktion auslösen
Sie können an so vielen Herausforderungen arbeiten, wie Sie möchten. Sie können/sollten Ihre Antworten direkt als Antwort auf diesen Thread einreichen.
!!! Bitte beginnen Sie beim Einreichen in der ersten Zeile mit der Frage, auf welche Herausforderung sich Ihre Antwort bezieht, z. B
HERAUSFORDERUNG A:
Das ist meine Antwort...
// this is my code
...
Im nächsten Treffen (18. Mai 2022) werden wir einige der Antworten präsentieren und ich werde die besten Antworten als Lösung für diesen Thread markieren.
Ich freue mich auf eure Einsendungen 
Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenIch werde einen kurzen Überblick darüber schreiben, worüber ich heute in der Besprechung gesprochen habe. Meine vollständigen Lösungen finden Sie in meinen früheren Beiträgen zu diesem Thema. Ich werde meine Challenge-A-Lösung so modifizieren, dass sie den Ordner SAMPLE_IMAGE von JMP verwendet, sodass Sie sie direkt ausführen können sollten.
Herausforderung A: Durch Klicken in eine Datentabellenzelle sollte etwas ausgelöst werden<BR />
Konzept: Verwendung der Spalteneigenschaft „Event Handler“.
Dies ist ziemlich einfach, indem Sie JMP das Skript für Sie erstellen lassen. Fügen Sie beispielsweise einen Event-Handler für eine Webseite hinzu und ändern Sie dann das Skript, um es Ihren Anforderungen besser anzupassen. Nachfolgend finden Sie meine Beispiellösung zum Öffnen eines Bilds in einer Zelle.
Column(dtx, "Picture") << Add Column Properties(
Set Property(
"Event Handler",
Event Handler(
Click(JSL Quote(Function({thisTable, thisColumn, iRow}, {},
New Window(Char(thisTable:"File Name"n[iRow]), New Image(thisTable:thisColumn[iRow]));
))),
Tip(JSL Quote(Function({thisTable, thisColumn, iRow}, {},
"Enlarge image " || Char(thisTable:"File Name"n[iRow]);
)))
)
)
);
Event-Handler können ziemlich leistungsfähig sein, da Sie beispielsweise Daten aus der Datenbank per Zellenklick abfragen können.
Herausforderung B: Das Schließen eines Fensters sollte eine Aktion auslösen
Konzept: Verwenden << Beim Schließen()</CODE></P>
<P><CODE class=" language-jsl">
Die Idee bei dieser Herausforderung bestand darin, eine Aktion auszuführen, wenn Graph Builder geschlossen ist. Dies ist eine ziemlich einfache Aufgabe, die mit << On Close() ausgeführt werden kann. Nachfolgend finden Sie eine leicht modifizierte Version der von bereitgestellten Lösung @Robbb
gb << On Close(
dist = dt << Distribution(Nominal Distribution(Column(:age)));
image = dist << Get Picture;
image << Save Picture($temp/age_dist.png, "png");
dist << Close Window();
);
Dabei ist zu berücksichtigen, dass Sie bei der Verwendung von Verweisen auf eine Datentabelle (in diesem Fall dt) höchstwahrscheinlich die falsche Tabelle schließen, wenn Sie eine neue Tabelle öffnen, bevor Sie gb schließen.
Sie können dieses Problem in diesem Beispielskript sehen:
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
biv = dt << Bivariate(Y(:Weight), X(:Height), Nonpar Density);
biv << On Close(
close(dt, no save);
);
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
Und dieses Skript bietet eine mögliche Lösung, indem es Eval(EvalExpr()) und Expr() verwendet, um einen expliziten Verweis auf die Tabelle zu erhalten
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
biv = dt << Bivariate(Y(:Weight), X(:Height), Nonpar Density);
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
Eval(EvalExpr(
biv << On Close(
Close(Expr(biv << Get Data Table), no save)
);
));
Möglicherweise können Sie die Funktion auch mit „On Close“ verwenden. In diesem Fall wird jedoch komplizierterer Code generiert, da Sie keinen Zugriff auf die Referenz der bivariaten Plattform haben, sondern auf das Fenster mit der bivariaten Plattform, sodass Sie das Fenster analysieren müssen name, der möglicherweise funktioniert oder auch nicht (möglicherweise gibt es eine Möglichkeit, im Fenster einen Verweis auf die Plattform zu erhalten).
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
biv = dt << Bivariate(Y(:Weight), X(:Height), Nonpar Density);
biv << On Close(function({this},
table_name = Trim Whitespace(Word(1, (this << Get Window Title), "-"));
If(Contains(Get Data Table List() << get name, table_name),
Close(Datatable(table_name), no save);
);
));
Herausforderung C: Ein Klick auf eine Grafik oder einen Bericht sollte eine Aktion auslösen
Konzept: Verwenden << Make Row State Handler()
</CODE></P>
<P>Dies hatte die unterschiedlichsten Lösungen und alle waren ein bisschen anders. <STRONG>Die große Herausforderung bei dieser Art von Skript besteht darin, zu entscheiden, wie Sie mit sich ständig ändernden Zeilenzuständen umgehen möchten.</STRONG> Eine Möglichkeit besteht darin, eine Schaltfläche zum Auslösen der Aktion zu verwenden (z. B<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/15435" target="_blank"> @Ressel</A> tat) anstelle von Row State Handler, dies ist meiner Meinung nach in diesem Fall die robusteste Option.</P>
<P> </P>
<P>Die übrigen Lösungen verwendeten einen Zeilenstatus-Handler und verschiedene Methoden (oder auch nicht), um die ausgewählten Zeilen ständig zu ändern. <STRONG>Beim Row State Handler ist zu beachten, dass er geänderte Zeilen zurückgibt.</STRONG> nicht nur ausgewählte Zeilen. Wenn Sie also nur an ausgewählten Spalten interessiert sind, müssen Sie dies berücksichtigen.</P>
<P> </P>
<P>In den meisten einfachen Fällen können Sie so etwas wie verwenden<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/9474" target="_blank"> @Georg</A> gab als Antwort.</P>
<PRE><CODE class=" language-jsl">f = Function({a},
dt << Subset(Selected Rows(1), Selected columns only(0))
);
rs = dt << make row state handler(f);
Eine Möglichkeit, die Zeilen zu verwalten, wäre die Erstellung eines assoziativen Arrays ( JMP ermöglicht die Verwendung von Matrix als Schlüssel in einem assoziativen Array ), in dem Sie die Zeilen sammeln, für die bereits eine Teilmenge erstellt wurde. Dies sollte funktionieren, solange Sie die Zeilenreihenfolge nicht ändern oder Zeilen hinzufügen/entfernen.
Unten finden Sie ein kurzes Beispiel für die Verwendung eines assoziativen Arrays zum Sammeln von Zeilen, die in Teilmengen unterteilt wurden. Im Beispiel suche ich nach Zeilen, die den Zeilenstatus 1 (ausgewählte Zeile) haben, und erstelle dann eine Teilmenge davon, falls sie noch nicht erstellt wurde. Ein Vorteil dabei ist, dass Sie die Datentabellenreferenzen auch im assoziativen Array speichern und schnell auf alle zugreifen können aa_subset_rows << Werte abrufen; Diese Lösung kann jedoch immer noch etwas fehlerhaft sein, wenn viele Zeilen ausgewählt werden, indem man die Maus gedrückt hält und darüber zieht.
Names Default To Here(1);
// Open Data Table
dt = Open("$SAMPLE_DATA/Growth Measurements.jmp", invisible);
gb = dt << Graph Builder(
Size(522, 452),
Show Control Panel(0),
Legend Position("Bottom"),
Graph Spacing(8),
Variables(X(:Age), Y(:Growth), Overlay(:Subject)),
Elements(Line(X, Y, Legend(13)))
);
aa_subset_rows = Associative Array();
f = Function({rows_changed},
//Rowstate 1 is selected row
cur_rows = Loc(dt << Get Row States, 1);
//if no rows are selected, don't try to create subsets
If(N Items(cur_rows) == 0,
return()
);
//compare to previous to prevent opening extensive abmount of subsets
If(Contains(aa_subset_rows , cur_rows),
return();
);
dt_subset = dt << Subset(Output table("selected_rows"), Rows(cur_rows));
aa_subset_rows[cur_rows] = dt_subset;
);
rs = dt << make row state handler(f);
Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenHerausforderung C:
Ich empfehle auf jeden Fall, solche Dinge mit Schaltflächen zu tun, da dadurch die Erstellung zu vieler Teilmengen verhindert wird. Aber hier bin ich der gegebenen Herausforderung gefolgt und habe eine einfache Überprüfung hinzugefügt, um sicherzustellen, dass wir nicht mindestens zweimal dieselbe Teilmenge erstellen.
Mehr sehen...
Mit dem Row State Handler können wir nicht auf das Ereignis der Mausfreigabe zugreifen, sodass wir trotzdem viele Teilmengen erstellen, wenn der Benutzer mehrere Zeilen nacheinander aus dem Diagramm auswählt (es könnte eine Möglichkeit geben, dies mit Mouse Box() zu tun, aber ich denke, die Verwendung der Schaltfläche würde dies tun). viel einfacher und einfacher sein).
Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenHerausforderung B:
Mehr sehen...
Names Default To Here(1);
// 2022_Q1 MakeOverChallenge: Action on mouse click in various ways
// Challenge B
dt = Open("$SAMPLE_DATA/Big Class.jmp");
//Use expression to make script a bit more clean IF this were to be expanded
create_dist = Expr(
dist = dt << Distribution(Nominal Distribution(Column(:age)), Histograms Only);
wait(1); // add wait so we can see that distribution is created
dist << Save Picture("$TEMP/Big_Class_age_dist.png", png);
dist << Close Window;
);
gb = dt << Graph Builder(
Size(528, 454),
Show Control Panel(0),
Variables(X(:height), Y(:weight)),
Elements(Points(X, Y, Legend(3)), Line Of Fit(X, Y, Legend(5)))
);
gb << On Close(create_dist);
// Open("$TEMP/Big_Class_age_dist.png"); // un-comment to open the image
Namen standardmäßig hier(1); // 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene Arten // Challenge B dt = Open("$SAMPLE_DATA/Big Class.jmp"); //Ausdruck verwenden, um das Skript etwas übersichtlicher zu gestalten, WENN dies erweitert werden soll create_dist = Expr( dist = dt << Distribution(Nominal Distribution(Column(:age)), Histograms Only); wait(1); // add Warten Sie, damit wir sehen können, dass die Verteilung erstellt wurde dist << Save Picture("$TEMP/Big_Class_age_dist.png", png); dist << Close Window; ); gb = dt << Graph Builder( Size(528, 454), Show Control Panel(0), Variables(X(:height), Y(:weight)), Elements(Points(X, Y, Legend(3)) , Anpassungslinie(X, Y, Legend(5))) ); gb << On Close(create_dist); // Open("$TEMP/Big_Class_age_dist.png"); // Kommentar entfernen, um das Bild zu öffnen
Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenHerausforderung A:
Hauptsächlich JMP-geschriebener Code mit „Spalteneigenschaften hinzufügen“. Außerdem wurde ein Beispiel zum Hinzufügen und Öffnen von URLs hinzugefügt
Mehr sehen...
Names Default To Here(1);
// Challenge A
path = "2022Q1_ChallengeA"; // path to images
{dtx} = Multiple File Import(
<<SET folder=""></SET>
Namen standardmäßig hier(1); // Challenge A path = "2022Q1_ChallengeA"; // Pfad zu Bildern {dtx} = Multiple File Import( <
Die Verwendung der Pfadvariablen SAMPLE_IMAGES (dies dient auch als Beispiel dafür, wie einfach es sein kann, bei der Skripterstellung Änderungen vorzunehmen; nur eine Variable zu ändern und das Skript funktioniert immer noch (ich habe eine URL aus der Liste entfernt, sodass den anderen Spalten keine leere Zeile hinzugefügt wird). )):
Names Default To Here(1);
// Challenge A
path = Get Path Variable("$SAMPLE_IMAGES");
{dtx} = Multiple File Import(
<<SET folder=""></SET>
Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenHerausforderung C
Was die Herausforderungen A und B betrifft, gab es leider kaum etwas anderes zu tun. Die angebotenen Lösungen schienen einwandfrei. Im Gegensatz dazu hatte ich das Gefühl, dass bei Herausforderung C noch eine gewisse Verbesserung möglich war. Ein paar Worte zu meiner Antwort
- Ich habe im Grunde den notwendigen Code gestohlen von hier ( @txnelson ist für mich wie viele andere Drehbuchautoren ein Rockstar)
- Ich habe das Diagramm durch die Einbeziehung sichtbarer Datenpunkte leicht modifiziert, damit es einfacher ist, einzelne Zeilen auszuwählen
- Nach Auswahl der Punkte im Diagramm wird die Datentabelle mit der Teilmenge nicht sofort geöffnet. Dies geschieht über die unterhalb der Grafik hinzugefügte Schaltfläche
Unten sehen Sie das vollständige Skript, einschließlich der geänderten Grafik.
// Open Data Table
dt = Open( "$SAMPLE_DATA/Growth Measurements.jmp",invisible );
// Report snapshot: Growth Measurements - Graph Builder
gb = dt << Graph Builder(
Size( 522, 452 ),
Show Control Panel( 0 ),
Legend Position( "Bottom" ),
Graph Spacing( 8 ),
Variables( X( :Age ), Y( :Growth ), Overlay( :Subject ) ),
Elements(
Points( X, Y, Legend( 17 ), Jitter Limit( 0 ) ), // added markers
Line( X, Y, Legend( 13 ) ) ),
SendToReport( // increased markers to decent size
Dispatch(
{},
"Graph Builder",
FrameBox,
{Marker Size( 6 ), Marker Drawing Mode( "Normal" )}
)
)
);
// my solution (stolen from here: https://community.jmp.com/t5/Discussions/Creating-a-Subset-from-an-Interactive-Graph/td-p/114459)
subsetButton = Button Box( "Dear user, Please press here to create a Subset of the Selected Points immediately",
If( N Rows( dt << get selected rows ) > 0,
dt << subset( selected rows( 1 ), selected columns( 0 ) )
)
);
Report( gb )["Graph Builder"] << append( subsetButton );
Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenHERAUSFORDERUNG A
Tut mir leid, dass ich mit meiner ursprünglichen Lösung voreilig vorgegangen bin ... Hier ist eine sauberere.
Names Default to Here ( 1 );
//path = <YOUR full="" path="" to="" where="" the="" images="" have="" been="" saved="">;
// eg.
// path = "C:\EventHandlerImages\";
path = "$DOCUMENTS\Scripting\2022Q1\ChallengeA\2022Q1_ChallengeA\";
//==========================================================================
//Multiple File Import is new in JMP 14
{dtx} = Multiple File Import(
<<SET folder=""></SET></YOUR>Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenHERAUSFORDERUNG A:
NOTIZ: Ich habe diese ältere Version beibehalten, da einige Leute sie bereits gesehen hatten, aber ich habe eine sauberere Lösung als veröffentlicht Antwort zu diesem.
Überhaupt keine schöne Lösung, aber sie erfüllt ihren Zweck ... Ich hoffe, dass ein eleganteres Exemplar auftaucht!
Dies muss nach dem StarterScript hinzugefügt werden:
// Defining the file name for an image placeholder for displaying on the OS when clicking:
pictFileName = Get Default Directory() || "verylonganduselessname.png"; //name for the temp image file (to be deleted at the end)
dtx:Picture << Set Property("tmpFileName", pictFileName); //saving the name so it can be retrieved from within the table
dtx << On Close( Delete File(pictFileName) ); //make sure we erase the temp image file at the end.
// Setting a Click event handler for the column of interest:
dtx:Picture << Set Property(
"Event Handler",
Event Handler(
Click(JSL Quote( Function(
{thisTable, thisColumn, iRow},
pictFileName = thisTable:thisColumn<< Get Property("tmpFileName"); //recover the path for a temp file
thisTable:thisColumn[iRow] << Save Image( pictFileName ); //save cell contents to temp file
Web( "file://" || pictFileName ) // open the image file
)
)
),
Tip(JSL Quote( Function(
{thisTable, thisColumn, iRow},
"click to open";
)
)
)
)
);
Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenHERAUSFORDERUNG C
Mit einer Mausbox war es nicht möglich, etwas auszuwählen, also habe ich zu einem Zeilenstatus-Handler gewechselt
Names Default To Here( 1 );
// Open Data Table
dt = Open( "$SAMPLE_DATA/Growth Measurements.jmp", invisible );
// Report snapshot: Growth Measurements - Graph Builder
gb = dt << Graph Builder(
Size( 522, 452 ),
Show Control Panel( 0 ),
Legend Position( "Bottom" ),
Graph Spacing( 8 ),
Variables( X( :Age ), Y( :Growth ), Overlay( :Subject ) ),
Elements( Line( X, Y, Legend( 13 ) ) )
);
active_subset = "";
first_subset = "false";
rsh = dt << make row state handler(
Function( {a},
subtbl = dt << Subset( Selected Rows( 1 ) );
gb << Bring Window To Front;
if(
first_subset == "true",
close(active_subset, no save)
);
active_subset = subtbl;
first_subset = "true";
)
);
Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenHERAUSFORDERUNG C
Das ist meine Antwort, siehe vollständiges Skript unten.
Der untere Teil fügt der Tabelle einen Zeilenstatus-Handler hinzu, der die Aktion auslöst (siehe Beispiel im Skriptindex).
Names Default To Here( 1 );
// Open Data Table
dt = Open( "$SAMPLE_DATA/Growth Measurements.jmp", invisible );
// Report snapshot: Growth Measurements - Graph Builder
gb = dt << Graph Builder(
Size( 522, 452 ),
Show Control Panel( 0 ),
Legend Position( "Bottom" ),
Graph Spacing( 8 ),
Variables( X( :Age ), Y( :Growth ), Overlay( :Subject ) ),
Elements( Line( X, Y, Legend( 13 ) ) )
);
// This is my code (Georg)
// (see Scripting Index "Make Row State Handler")
// Define a function, that does the action
f = Function( {a},
Current Data Table() << Subset( Selected Rows( 1 ), Selected columns only( 0 ) )
);
// Set up a row state handler, that triggers the execution of a function on any change of row states,
// a change on row selection by clicking on a line in Graph Builder is a change of row states in the table
rs = dt << make row state handler( f );Betreff: 2022_Q1 MakeOverChallenge: Aktion auf Mausklick auf verschiedene ArtenHERAUSFORDERUNG B
Fügen Sie dies am Ende des Skripts hinzu:
gb << On Close(
dist = dt << Distribution( Nominal Distribution( Column( :age ) ) );
image = dist << Get Picture;
path = "$temp/age_dist.png";
image << Save Picture( path, "png" );
dist << Close Window();
Open( path );
);