脚本在脚本编辑器中有效,但在菜单项上无效(获取列名称的行为不同)当我从脚本编辑器运行以下脚本时,它工作正常。但是,当我从在“视图”->“自定义”中创建的自定义菜单项运行它时,它不起作用。我已追踪到“获取列名称”函数的行为不一样。当我在使用 Get Property 之前放置一条打印语句来输出每个列名称及其类型的值时,我在从脚本编辑器运行时看到了这一点(例如):
:exec_typ
“姓名”
然而,当我从菜单项运行它时,我得到这个:
执行类型
“姓名”
注意缺少冒号。(无论冒号做什么,我不知道。)
最终,脚本崩溃了,因为当我尝试在名为 exec_typ 的列上运行 Get Property 函数时,JMP 无法将其识别为列名或类似名称:
在访问或评估 'Send' 时发送期望可编写脚本的对象{7},colNames[colInd] << /*###*/Get Property( "Spec Limits" ) /*###*/
知道到底发生了什么吗?为什么从脚本编辑器调用与从菜单快捷方式调用“获取列名称”函数的行为不同?
代码如下。是的,有些内容很混乱。
//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. 我相信我的代码比你的方法运行得更快的主要原因是基于以下两项。
A。 是的,公式已优化。
b. 使用 dt << SelectWhere 加上能够一次分配给所有选择的行是非常快的。使用代码中的所有“IF”语句循环遍历数据表非常慢。
3.关于你的角色规格限制值。您如何分配规格限制?“规格限制”列属性应仅允许数值。如果您使用 Substr() 等字符函数访问规格限制列表,您将返回字符串。查看脚本指南,了解如何操作 JSL 列表
回复:脚本可以在脚本编辑器中工作,但不能在菜单项上工作(获取列名称的行为不一样)感谢吉姆的剧本! 你是对的,我不知道变量作用域在 JMP 脚本中是如何工作的,除了我看到一些证据表明声明的变量默认为局部变量。
您是如何让您的脚本在这些论坛上正确显示的?当我将代码粘贴到这些论坛的代码窗口中时,它会搞乱格式并删除所有制表符和空格缩进。好在我们没有尝试共享 Python 代码!
不管怎样,我正在调整我的脚本以使用你的元素,它终于可以工作了。我尝试直接使用您的脚本与 dt= current data table();又进行了一两次编辑,但没有成功。我知道我的脚本效率低下,但例如,我将 USL 和 LSL 转换为数字的所有尝试都失败了,因此我不得不将其转换为字符串并使用子字符串。如果我在评论中进行调整以提取所有规格限制一次,那么这不会太重要。查看打开的文件示例甚至很有用,因为我真正想做的是可以选择从与我正在分析的文件不同的文件中提取测试限制!
对我来说奇怪的是你的暗示(因为你说你的脚本更快)添加列和删除它们比两个嵌套的 For 循环更有效。计算机仍然需要分析数据表中的每个单元格。JMP 是否经过优化,使得设置和运行公式更加高效?我无法让你的方法真正发挥作用来尝试找出答案,也许我应该尝试后续提出者的建议。
顺便说一句,我的数据表大约有 600 列,可能有数万行,因此可能需要考虑执行效率。
不管怎样,为了让我的脚本工作,我需要做的最小的改变就是替换所有
列名[列名]
和
列(dt,colNames [colInd])。
尽管我无法让它与我的数据文件一起使用,但我会尝试从您的脚本中调整更多元素。
回复:脚本可以在脚本编辑器中工作,但不能在菜单项上工作(获取列名称的行为不一样)吉姆,
不错的工作。我需要添加
dt << Run Formulas;
在 Eval(Parse(theExpr)) 之后和删除公式语句之前,在编写良好的脚本的两个位置。
回复:脚本可以在脚本编辑器中工作,但不能在菜单项上工作(获取列名称的行为不一样)我的假设是,由于您没有专门确定变量的范围(:),因此在尝试在两种不同的环境中运行时会遇到问题。我观察到的另一件事是,您的方法将导致一段非常慢的代码。鉴于此,我重写了您的脚本,使用了一些我相信在这两种环境中都适用的方法,并且运行速度也会更快。下面的脚本针对使用 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)));