脚本在脚本编辑器中有效,但在菜单项上无效(获取列名的行为不同)当我从脚本编辑器运行以下脚本时,它工作正常。但是当我从我在 View->Customize 中创建的自定义菜单项运行它时,它不起作用。我已经将其追溯到 Get Column Names 函数的行为不同。当我在使用 Get Property 之前放置一个打印语句来输出每个列名称及其类型的值时,我在从脚本编辑器运行时看到了这个(例如):
:exec_typ
“姓名”
但是,当我从菜单项运行它时,我得到了这个:
exec_typ
“姓名”
注意没有冒号。(无论冒号做什么,我都不知道。)
最终,脚本崩溃了,因为当我尝试在名为 exec_typ 的列上运行 Get Property 函数时,JMP 无法将其识别为列名或类似名称:
Send 需要 Scriptable Object{7} 访问或评估 'Send' , colNames[colInd] << /*###*/Get Property( "Spec limits" ) /*###*/
知道到底发生了什么吗?如果从脚本编辑器调用与从菜单快捷方式调用,为什么 Get Column Names 函数的行为会有所不同?
代码如下。是的,有些是乱七八糟的。
//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;
);
回复:脚本在脚本编辑器中有效,但不适用于菜单项(获取列名的行为不同)1. 要让代码显示为 JSL,您需要使用输入窗口顶部的 工具来输入文本。
2. 我相信我的代码比你的方法运行得更快的主要原因是基于 2 项。
一个。 是的,公式已经过优化。
湾。 使用 dt << Select Where 加上能够一次分配给所有 selcted 行的速度非常快。循环使用您的代码具有的所有“IF”语句的数据表非常慢。
3.关于你的字符规格限制值。您如何分配规格限制?Spec Limits 列属性应该只允许数值。如果您通过使用像 Substr() 这样的字符函数访问 Spec Limits 列表,您将获得字符串。查看脚本指南以了解如何操作 JSL 列表
回复:脚本在脚本编辑器中有效,但不适用于菜单项(获取列名的行为不同)感谢吉姆的剧本! 没错,我不知道 JMP 脚本中的变量作用域是如何工作的,除了我已经看到一些证据表明声明的变量默认为局部变量。
您是如何让您的脚本在这些论坛上正确显示的?当我将代码粘贴到这些论坛的代码窗口中时,它会破坏格式并删除所有选项卡和空格缩进。还好我们没有尝试共享 Python 代码!
无论如何,我正在调整我的脚本以使用您的元素,并且它最终已经开始工作了。我尝试直接使用您的脚本与 dt= current data table();和另一个或两个编辑,但它没有工作。我知道我的脚本效率低下,但是例如,我所有将 USL 和 LSL 转换为数字的尝试都失败了,所以我不得不将其转换为字符串并使用子字符串。如果我在评论中进行调整以仅提取一次所有规格限制,那么这不会太重要。查看一个打开的文件示例也很有用,因为我真正想做的是可以选择从不同的文件中提取测试限制,而不是我正在分析的文件!
对我来说奇怪的是你的暗示(因为你说你的脚本更快)添加列和删除它们比两个嵌套的 For 循环更有效。计算机仍然必须分析数据表中的每个单元格。JMP 是否进行了优化,以使设置和运行公式更有效?我无法让您的实际工作方法试图找出答案,也许我应该尝试后续装腔作势者的建议。
顺便说一句,我的数据表大约有 600 列,可以有数万行,因此可能需要考虑执行效率。
无论如何,为了使我的脚本正常工作,我需要做的最小更改就是替换所有
colNames[colInd]
和
列(dt,colNames[colInd])。
即使我无法让它与我的数据文件一起使用,我也会尝试从您的脚本中调整更多元素。
回复:脚本在脚本编辑器中有效,但不适用于菜单项(获取列名的行为不同)吉姆,
不错的工作。我需要添加
dt << Run Formulas;
在 Eval(Parse(theExpr)) 之后和 delete 公式语句之前,在你写得很好的脚本的两个地方。
回复:脚本在脚本编辑器中有效,但不适用于菜单项(获取列名的行为不同)我的假设是,由于您没有具体确定变量的范围 (:),因此您在尝试在 2 个不同的环境中运行时会遇到问题。我观察到的另一项是您的方法将导致一段非常慢的代码。鉴于此,我已经重写了您的脚本,使用了一些我相信在这两种环境中都可以使用的方法,并且运行速度也会更快。下面的脚本针对随 JMP 分发的半导体能力数据表运行。但是,如果您只是去掉对打开该表的引用,以及数据表的打开之后的语句,并将它们替换为您的
dt = 当前数据表();
该代码应该适用于您的数据。
我已经注释了下面的代码,所以我认为您应该能够遵循它。另外,我强烈建议您阅读随您的 JMP 安装分发的脚本指南。
帮助==>书籍==>脚本指南
它会告诉你所有这些疯狂的冒号是怎么回事
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)));