腳本在腳本編輯器中有效,但在菜單項上無效(獲取列名稱的行為不同)當我從腳本編輯器運行以下腳本時,它工作正常。但是,當我從在“視圖”->“自定義”中創建的自定義菜單項運行它時,它不起作用。我已追踪到“獲取列名稱”函數的行為不一樣。當我在使用 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)));