Le script fonctionne dans l'éditeur de script mais pas sur l'élément de menu (Get Column Names ne se comportant pas de la même manière)Lorsque j'exécute le script suivant à partir de l'éditeur de script, cela fonctionne correctement.Mais lorsque je l'exécute à partir d'un élément de menu personnalisé que j'ai créé dans Affichage-> Personnaliser, cela ne fonctionne pas.Je l'ai tracé jusqu'à ce que la fonction Get Column Names ne se comporte pas de la même manière.Lorsque je mets une instruction d'impression pour afficher la valeur de chaque nom de colonne et son type avant d'utiliser Get Property dessus, je vois ceci (par exemple) lors de l'exécution à partir de l'éditeur de script :
:type_exec
"Nom"
CEPENDANT, lorsque je l'exécute à partir de mon élément de menu, j'obtiens ceci:
exec_typ
"Nom"
Remarquez l'absence du côlon.(Quoi que fasse le côlon, je ne sais pas.)
En fin de compte, le script se bloque car lorsque j'essaie d'exécuter la fonction Get Property sur la colonne nommée exec_typ, JMP ne le reconnaît pas comme un nom de colonne ou quelque chose comme ça :
Send attend un objet inscriptible{7} dans l'accès ou l'évaluation de 'Send' , colNames[colInd] << /*###*/Get Property( "Spec limits" ) /*###*/
Une idée de ce qui se passe?Pourquoi la fonction Get Column Names se comporte-t-elle différemment si elle est appelée depuis l'éditeur de scripts ou depuis un raccourci de menu ?
Code ci-dessous.Oui, certaines d'entre elles sont désordonnées.
//Reports all failing tests for a unit. Not temperature-smart (yet!)
dt = Current Data Table();
colNames = dt << get column names(Numeric);
//I need to clean up the add columns scripts... once I understand how it works.
dt << add multiple columns(
"Num Tests Failing",
1,
After( "20:Neg_Contact:Cont_int2[1]" ),
numeric( 10 )
);
colf = Column( "Num Tests Failing" );
colf << Modeling Type ( Nominal );
dt << add multiple columns(
"Failing Tests",
1,
After( "20:Neg_Contact:Cont_int2[1]" ),
numeric( 10 )
);
colf = Column( "Failing Tests" );
colf << Data type( Character );
For (i = 1, i <= N Rows(dt), i++,
Row() = i;
failingTests = "";
NumOfFailingTests = 0;
If (:Name("HBIN_NAM") != "Good" & :Name("HBIN_NAM") != "1:Good" , //It's a fail
//Efficiency could be improved by extracting all spec limits first.
For (colInd = 1, colInd <= N Items(colNames), colInd++,
//print statements for debugging.
print(colNames[colInd]);
print(Type(colNames[colInd]));
//THIS IS WHERE IT KEEPS CRASHING
specLimits = colNames[colInd] << Get Property ("Spec limits");
LSL_Char = Char(specLimits[1]);
USL_Char = Char(specLimits[2]);
LSL_Char = SubStr(LSL_Char, 5, (Length(LSL_Char) - 5));
USL_Char = SubStr(USL_Char, 5, (Length(USL_Char) - 5));
LSL_Num = 0; //initializing value to set its scope; is this necessary? Donno.
USL_Num = 0;
If(LSL_Char == "." | LSL_Char == "",
LSL_Char = "NO LIMIT",
//else
LSL_Num = Num(LSL_Char);
);
If(USL_Char == "." | USL_Char == "",
USL_Char = "NO LIMIT",
//else
USL_Num = Num(USL_Char);
);
failedTest = 0;
If(LSL_Char != "NO LIMIT",
If( colNames[colInd][i] < LSL_Num,
failedTest = 1;
NumOfFailingTests = NumOfFailingTests + 1;
);
);
If(USL_Char != "NO LIMIT",
If( colNames[colInd][i] > USL_Num,
failedTest = 1;
NumOfFailingTests = NumOfFailingTests + 1;
);
);
If(failedTest == 1,
failingTests = failingTests || Char(colNames[colInd]) || "; ";
);
);
);
:Name( "Failing Tests" )[i] = failingTests;
:Name( "Num Tests Failing" )[i] = NumOfFailingTests;
);
Re : Le script fonctionne dans l'éditeur de script mais pas sur l'élément de menu (Get Column Names ne se comporte pas de la même manière)1. Pour que le code s'affiche en JSL, vous devez utiliser l'outil en haut de la fenêtre de saisie pour saisir votre texte.
2. La principale raison pour laquelle je pense que mon code fonctionnera plus rapidement que votre méthode est basée sur 2 éléments.
un. Oui, les formules sont optimisées.
b. L'utilisation de dt << Select Where associée à la possibilité d'affecter à toutes les lignes sélectionnées en même temps est extrêmement rapide.Faire une boucle dans une table de données avec toutes les instructions "IF" de votre code est très lent.
3. Concernant les valeurs limites de vos spécifications de personnage.Comment attribuez-vous les limites de spécification ?La propriété de colonne Spec Limits ne doit autoriser que des valeurs numériques.Si vous accédez à la liste Spec Limits en utilisant des fonctions de caractères telles que Substr(), vous allez récupérer des chaînes de caractères.Jetez un oeil dans le Guide de script sur la façon de manipuler les listes JSL
Re : Le script fonctionne dans l'éditeur de script mais pas sur l'élément de menu (Get Column Names ne se comporte pas de la même manière)Merci pour le scénario Jim ! Vous avez raison, je n'ai aucune idée du fonctionnement de la portée des variables dans le script JMP, sauf que j'ai vu des preuves suggérant que les variables déclarées sont par défaut des variables locales.
Comment avez-vous fait pour que votre script s'affiche correctement sur ces forums ?Lorsque je colle du code dans la fenêtre de code sur ces forums, cela bousille le formatage et supprime tous les onglets et l'indentation des espaces blancs.Heureusement que nous n'essayons pas de partager du code Python !
Quoi qu'il en soit, j'adapte mon script pour utiliser des éléments du vôtre, et cela fonctionne déjà enfin.J'ai essayé d'utiliser votre script directement avec dt= table de données actuelle (); et une autre modification ou deux, mais cela n'a pas fonctionné.Je sais que mon script est inefficace, mais par exemple, toutes mes tentatives de conversion de l'USL et du LSL en nombres ont échoué, j'ai donc dû simplement le convertir en une chaîne et utiliser une sous-chaîne.Si je fais l'ajustement que je note dans les commentaires pour extraire toutes les limites de spécifications une seule fois, cela n'aura pas trop d'importance.Il est même utile de voir un exemple de fichier ouvert, car ce que j'aimerais vraiment faire, c'est avoir la possibilité d'extraire les limites de test de fichiers différents de celui que j'analyse !
Ce qui est étrange pour moi, c'est votre implication (parce que vous avez dit que votre script était plus rapide) que l'ajout de colonnes et leur suppression seraient plus efficaces que deux boucles For imbriquées.L'ordinateur doit encore analyser chaque cellule de votre tableau de données.JMP est-il optimisé pour que la définition et l'exécution des formules soient plus efficaces ?Je n'arrive pas à faire fonctionner votre approche pour essayer de le découvrir, peut-être devrais-je essayer ce que le poseur de suivi suggère.
Soit dit en passant, mes tables de données ont quelque chose comme 600 colonnes et peuvent avoir des dizaines de milliers de lignes, ce qui peut nécessiter des considérations d'efficacité d'exécution.
Quoi qu'il en soit, le changement minimum que j'avais besoin de faire pour que mon script fonctionne était de remplacer tous les
colNames[colInd]
avec
Column( dt, colNames[colInd] ) .
Même si je n'arrive pas à le faire fonctionner avec mes fichiers de données, je vais essayer d'adapter quelques éléments supplémentaires de votre script.
Re : Le script fonctionne dans l'éditeur de script mais pas sur l'élément de menu (Get Column Names ne se comporte pas de la même manière)Jim,
Bon travail.j'avais besoin d'ajouter
dt << Run Formulas;
après Eval(Parse(theExpr)) et avant l'instruction de formule de suppression, à deux endroits de votre script bien écrit.
Re : Le script fonctionne dans l'éditeur de script mais pas sur l'élément de menu (Get Column Names ne se comporte pas de la même manière)Mon hypothèse est que, puisque vous ne définissez pas spécifiquement la portée de vos variables (:), vous rencontrez des problèmes lorsque vous essayez d'exécuter dans les 2 environnements différents.L'autre élément que j'ai observé est que votre méthode va aboutir à un morceau de code très lent.Compte tenu de cela, j'ai réécrit votre script en utilisant certaines méthodes qui, à mon avis, fonctionneront dans les deux environnements et s'exécuteront également beaucoup plus rapidement.Le script ci-dessous s'exécute sur la table de données Semiconductor Capability qui est dédistribuée avec JMP.Mais si vous supprimez simplement la référence à l'ouverture de cette table, ainsi que l'instruction suivant l'ouverture de la table de données et remplacez-les par votre
dt = table de données actuelle();
le code devrait fonctionner sur vos données.
J'ai annoté le code ci-dessous, donc je pense que vous devriez pouvoir le suivre.De plus, JE VOUS CONSEILLE TRÈS FORT de lire le Guide de création de scripts distribué avec votre installation de JMP.
Aide==>Livres==>Guide de script
Il vous dira tout sur ce que sont ces colons fous
Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/semiconductor capability.jmp" );
dt << delete columns( {2, 3, 4} );
// Get the numeric column names as strings
colNames = dt << get column names( Numeric, string );
// Create the new calculated columns
// They will be populated later
dt << New Column( "Num Tests Failing", numeric );
dt << New Column( "Failing Tests", character );
// Create a new column for each column in the colNames list
// and populate the colNames name, if it does NOT pass
For( i = 1, i <= N Items( colNames ), i++,
// Create the new colum
dt << New Column( "PassFail " || Char( i ), character );
// Get the Spec Limits for the first column
specLimits = Column( dt, colNames[i] ) << get property( "Spec Limits" );
// If no Spec Limits are found, do not process
If( Is Empty( specLimits ) == 0,
// Get the USL and LSL and if not present set to missing
LSL = Try( specLimits["LSL"], . );
USL = Try( specLimits["USL"], . );
// If the LSL is not missing process
If( Is Missing( LSL ) == 0,
// Find all rows where the colNames column is less than
// the LSL
dt << select where( As Column( dt, colNames[i] ) < LSL );
// If any rows are selected, then process
If( N Rows( dt << get selected rows ) > 0,
// Set the value in the PassFail column to the name of
// the colNames being processed. This will allow for
// the counting and the concatenating for the new
// calculation columns
Column( dt, "PassFail " || Char( i ) )[dt << get selected rows] = colNames[i]
|| "; "
);
);
// See above comments for LSL
If( Is Missing( USL ) == 0,
dt << select where( As Column( dt, colNames[i] ) > USL );
If( N Rows( dt << get selected rows ) > 0,
Column( dt, "PassFail " || Char( i ) )[dt << get selected rows] = colNames[i]
|| "; "
);
);
);
);
// Clean up and selected columns
dt << clear select;
// Create the command string required for the formula for the
// Failing Tests, which is a concatenated string of all of the
// PassFail columns.
theExpr = "dt:Failing Tests << set formula(Concat(:PassFail 1";
For( i = 2, i <= N Items( colNames ), i++,
theExpr = theExpr || ",:PassFail " || Char( i )
);
theExpr = theExpr || "))";
// Execute the command string
Eval( Parse( theExpr ) );
// Delete the formula, which will remove the formula, but not
// the calculated values
dt:Failing Tests << delete formula;
// Create the command string for the Num Tests Failing column
// The count is the sum of the "True" Boolean comparisions.
// That is, if PassFail 1 != "", it will be "True" and therefore
// will have the value of 1. If the cell is blank, it will have a
// value of 0. The sum of all of these comparisons will be equal to
// the number of non passing parameters(tests)
theExpr = "dt:Num Tests Failing << set formula(sum(:PassFail 1 != \!"\!"";
For( i = 2, i <= N Items( colNames ), i++,
theExpr = theExpr || ",:PassFail " || Char( I ) || " != \!"\!""
);
theExpr = theExpr || "));";
Eval( Parse( theExpr ) );
dt:Num Tests Failing << delete formula;
// Delete all of the PassFail columns, just to clean up the data table
dt << delete columns(index(n cols(dt)-N items(colNames)+1,ncols(dt)));