腳本在腳本編輯器中有效,但在菜單項上無效(獲取列名的行為不同)當我從腳本編輯器運行以下腳本時,它工作正常。但是當我從我在 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)));