[JMP Pro 14.1.0, sistema operativo W7 a 64 bit]
Carissimi,
Sto lavorando all'automazione di una tabella dati per alcuni clienti. La tabella dati contiene una colonna di data e diverse colonne di proprietà del prodotto, tutte con limiti di specifica.
Una delle cose che sto cercando di fare è aggiungere alla tabella dati nuovi script in modo che il cliente possa facilmente fare clic sul pulsante verde nella tabella dati e ottenere il grafico di controllo per qualsiasi proprietà a cui è interessato.
Ho un elenco chiamato "SpecList" che contiene tutti i nomi delle colonne nella tabella dati e una tabella dati delle specifiche con i soliti nomi delle colonne _LSL, _USL e _Target necessari per lo strumento "gestisci limiti specifiche" per la qualità e controllo del processo.
Mi piacerebbe generare i nuovi script con un ciclo For all'interno della funzione New Script: almeno questo è il concetto. Di seguito è riportato un esempio di ciò che vorrei inviare alla tabella, dove vorrei che [1] alla fine diventasse una [i] in un ciclo For:
dtperf << New Script(
"Control Chart " || SpecList[1],
Control Chart Builder(
Size( 534, 454 ),
Show Control Panel( 0 ),
Variables( Subgroup( :Date ), Y( Column(dtperf, SpecList[1]) ) ),
Chart( Position( 1 ), Limits ),
Chart( Position( 2 ), Limits ),
SendToReport(
Dispatch(
{},
SpecList[1],
ScaleBox,
{Add Ref Line( dtspecs:Name( "_LSL" )[1], "Solid", "Blue", "LSL", 1 ), Add Ref Line(
dtspecs:Name( "_USL" )[1],
"Solid",
"Blue",
"USL",
1
), Add Ref Line( dtspecs:Name( "_Target" )[1], "Solid", "Blue", "USL", 1 )}
)
)
)
);Alcune parti funzionano come intendo, altre no. Il nome del nuovo script funziona come previsto. Ho dei problemi, in particolare con la parte Dispatch. Dopo "Dispatch( {} , SpecList[1],...." e con le sezioni Add Ref Line().
Il Dispatch SpecList[1] invia letteralmente SpecList[1] invece di inserire il testo dall'elenco. Quindi, nella porzione Aggiungi riga di riferimento, invia letteralmente anche dtspecs:Name("_LSL")[1] invece del valore dalla tabella dati. Di seguito è riportato lo script salvato nella tabella dati:
Control Chart Builder(
Size( 534, 454 ),
Show Control Panel( 0 ),
Variables( Subgroup( :Date ), Y( Column(dtperf, SpecList[1]) ) ),
Chart( Position( 1 ), Limits ),
Chart( Position( 2 ), Limits ),
SendToReport(
Dispatch(
{},
SpecList[1],
ScaleBox,
{Add Ref Line( dtspecs:_LSL[1], "Solid", "Blue", "LSL", 1 ),
Add Ref Line( dtspecs:_USL[1], "Solid", "Blue", "USL", 1 ),
Add Ref Line( dtspecs:_Target[1], "Solid", "Blue", "USL", 1 )}
)
)
)Ho provato Char(), Num(), Try() ed Eval() avvolti nelle sezioni del codice pertinente per vedere se avrebbe funzionato, ma non funziona.
Inoltre, la colonna Y nelle Variabili non funziona. Invia nuovamente esattamente ciò che è scritto invece del riferimento a cui punta. Tuttavia, quando evidenzio la funzione Control Chart Builder nel mio script originale sopra (primo script), funziona perfettamente.
Mi piacerebbe un modo per risolvere questo problema in modo che invii i valori effettivi a cui si fa riferimento al nuovo script anziché allo script JSL letterale. Il motivo è che sto cercando di scrivere lo script nel modo più generico possibile in modo che possa essere applicato ad altri prodotti e non sia necessario scavare troppo in profondità nello script per modificarlo/aggiornarlo per implementarlo per gli altri prodotti.
Penso che parte del problema sia che i nomi delle mie variabili risiedono tutti nel mio script primario (ho impostato i nomi predefiniti su qui (1)) e quando invia un nuovo script alla tabella dati, non sa come valutare a riferimento a una variabile non definita. Potrebbe essere necessario inviare queste variabili allo script scritto nella tabella dati, ma non sono sicuro di come. Preferirei neanche generare una variabile globale.
Grazie!,
DS
CIAO @nathan-clark E @ian_jmp ,
Apprezzo davvero il tuo feedback e le tue idee. Alcune delle cose utilizzate vanno oltre il mio livello in questo momento e non sono riuscito a capire come implementarle.
D'altra parte, in base al tuo feedback, ho modificato il mio codice e l'ho fatto funzionare in un modo che avesse senso per me. Potrebbe non essere molto elegante, ma funziona e fa esattamente quello che avevo intenzione di fare.
Una volta realizzato che il ciclo For doveva essere all'esterno di tutto, ha funzionato benissimo. Ha senso ora che devo trasformare CharList[i] in un'espressione che poi deve essere eseguita attraverso un EvalExpr, che poi deve essere valutato per inviare alla tabella dati il nuovo script con gli input desiderati .
Di seguito è riportato il mio codice su come l'ho fatto funzionare.
Grazie per l'aiuto!
DS
For( i = 1, i <= N Items( ChartList ), i++,
Eval(
Eval Expr(
dtperf << New Script(
"Control Chart " || Expr( ChartList[i] ),
Control Chart Builder(
Size( 534, 454 ),
Show Control Panel( 0 ),
Variables( Subgroup( :Date ), Y( Expr( Column( dtperf, ChartList[i] ) ) ) ),
Chart( Position( 1 ), Limits ),
Chart( Position( 2 ), Limits ),
SendToReport(
Dispatch(
{},
Expr( ChartList[i] ),
ScaleBox,
{Add Ref Line( Expr( dtspecs:Name( "_LSL" )[i] ), "Solid", "Blue", "LSL", 1 ),
Add Ref Line( Expr( dtspecs:Name( "_USL" )[i] ), "Solid", "Blue", "USL", 1 ), Add Ref Line(
Expr(
dtspecs:Name( "_Target" )[i]
),
"Solid",
"Blue",
"USL",
1
)}
)
)
)
)
)
)
);FWIW, e probabilmente preferenza personale, ma tendo a usare 'SubstituteInto()' per questo genere di cose:
NamesDefaultToHere(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
// Template script for Control Chart Builder
myCCB =
Expr(
Control Chart Builder(
Size( 529, 453 ),
Show Control Panel( 0 ),
Show Capability( 0 ),
Variables( Y( YTBD ) ),
Chart( Position( 1 ), Limits( Sigma( "Moving Range" ) ) ),
Chart( Position( 2 ), Limits( Sigma( "Moving Range" ) ) ),
SendToReport(
Dispatch(
{},
yNameTBD,
ScaleBox,
{Add Ref Line( HLineTBD, "Dashed", "Green", "", 1 )}
)
)
)
);
// Update the template script
SubstituteInto(myCCB,
Expr(yTBD), Column(dt, "height"),
Expr(yNameTBD), "height",
Expr(HLineTBD), 55
);
// Save the script in the table
CMD = Expr(dt << newScript("My Control Chart Builder", scriptTBD));
SubstituteInto(CMD,
Expr(scriptTBD), NameExpr(myCCB)
);
CMD;
Il modo migliore che ho trovato per farlo è usare Eval() e EvalExpr() ... fondamentalmente, le variabili nello script sono espressioni e eval espressione le valuta in modo che la valutazione finale dello script della tabella abbia i valori effettivi, non quelli variabili. Di seguito è riportato un rapido esempio che ho preso in cui ho creato uno script di tabella e inserirà i nomi di colonna specifici anziché la variabile (parseUnique). parseUnique viene creato inserendo una stringa di testo per il nome della colonna nella funzione :Name() in modo che i nomi delle colonne funzionino meglio.
Non devo preoccuparmi delle variabili che creo all'interno dell'espressione (tblName), ma tutte le variabili che provengono da fonti esterne diventano espressioni nella funzione.
parseUnique = EvalInsert(":Name(\!"^uniqueCol^\!")");Eval(
EvalExpr(
dt_algorithm << New Script("Make justResults",
tblName = currentdatatable()<<GETNAME></GETNAME>