当公式包含缺失列时,我会捕获错误。在以下示例中,表格包含 2 列。添加使用不存在的列的新列,结果会丢失结果(正确),并且会阻止我的脚本的错误,我无法捕获该错误,因为 try 语句不起作用。有解决方法吗?
dt= New Table( "Test",
Add Rows( 1 ),
New Column( "A",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [2] )
),
New Column( "B",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Selected,
Set Values( [1] )
)
);
formula=":Name(\!"C\!") - :Name(\!"B\!")";
try(
eval(parse("dt << new column(\!"value\!", Numeric, \!"Continuous\!", Formula(" ||formula || "))"));
,
error="missing column";
);
@antonio-domenic ,我相信您想要的是在尝试基于公式创建列之前确定该表是否包含给定公式的适当列?如果您能够在尝试创建列之前确定这一点,您将不太可能遇到脚本停止错误。
好消息是,确定公式所依赖的所有外部名称非常简单——它们应该只是当前数据表的列名。(最好的做法是不要让公式依赖于当前范围内的变量,该变量将在将来的某个时候失去范围,从而导致公式出错)。
下面是一些示例代码,其中包含一个函数,可以递归地解析任何悬空名称的表达式(公式当然只是表达式)。然后可以检查表的列名,如果列名满足公式就应用:
Names Default to Here( 1 );
dt= New Table( "Test",
Add Rows( 1 ),
New Column( "A",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [2] )
),
New Column( "B",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Selected,
Set Values( [1] )
)
);
//recursively find all unassigned names within the formula -- we can test these against the column names
get dangling names = Function( {formula},
{Default Local},
parse formula = Function( {expr, names = {}, assigns = {}},
{Default Local},
If( Contains( Head Name( expr ), "[" ) & Contains( Head Name( expr ), "]" ), // deal with the exceptional case where JMP doesn't arg-parse out this pattern...
items = Words( Head Name( expr ), "[" );
Summation( i = 1, N Items( items ),
Try(
item = Word( 1, items[i], "]" );
If( Is Missing( Num( item ) ),
{n, a} = Recurse( Parse( item ) );
Insert Into( names, n );
Insert Into( assigns, a );
)
);<BR /> 0
)
,
If( Head Name( expr ) == "Assign", // if a variable is assigned within the formula then we don't care to check it (the formula shouldn't be direclty affecting other columns, it bad practice!)
Insert Into( assigns, Char( Arg( expr, 1 ) ) )
,
Head Name( expr ) != Char( Name Expr( expr ) ), // Need to recursively parse here
Summation( i = 1, N Arg( expr ),
{n, a} = Recurse( Arg( expr, i ) );
Insert Into( names, n );
Insert Into( assigns, a );
0
);
,
Insert Into( names, Char( Name Expr( expr ) ) ) // found a name
);
);
Eval List( {Associative Array( names ) << Get Keys, Associative Array( assigns ) << Get Keys} )
);
{names, assigns} = parse formula( Name Expr( formula ) );
names = Associative Array( names );
assigns = Associative Array( assigns );
names << Remove( assigns );
names = names << Get Keys;
names
);
formulas = {};
Insert Into( formulas, Expr( :Name("C") - :Name("B") ) );
local var = [1 => 3, 2 => 4];
Insert Into( formulas, Eval Expr(
var = Expr( local var );
var[:C][:F] + :D
);
);
Insert Into( formulas, Expr( :A + :B ) );
Insert Into( formulas, Expr( :A + :B - Sin( :D</img> + Cos( :E - :Name("flamingo@fish" ) ) ) ) );
For( i = 1, i <= N Items( formulas ), i++,
table columns = dt << Get Column Names( "String" );
Write( "\!N" );
Show( table columns );
formula references = get dangling names( formulas[i] );
refs = {};
For( j = 1, j <= N Items( formula references ), j++,
refs[j] = Contains( table columns, formula references[j] ) > 0
);
Show( formulas[i] );
Show( formula references );
Print( If( Sum( refs ) == N Items( formula references ), "OKAY", "NOT OKAY" ) );
If( Sum( refs ) == N Items( formula references ), // The table contains all the necessary columns, okay to add the new column!
Eval( Eval Expr(
dt << New Column( "FORMULA", <<FORMULA></FORMULA>如果您有任何问题,请告诉我!
约旦,
在创建公式列之前进行测试可能会更好。 因此,执行 if 语句以查看该列是否存在...如果不存在,则不要创建公式列。
谢谢,不过用处不大。 问题是我自动提取了一些数据(通过脚本)并且它们中的任何一个都可能丢失(但我事先不知道是否以及丢失了哪些)。 当找到丢失的列时脚本停止,这是真正的问题。 一个好的解决方案可能是 try 语句,但它不起作用。
如果缺少该列,我不确定您希望最终结果是什么,但以下是处理该问题的一种方法
dt = New Table( "Test",
Add Rows( 1 ),
New Column( "A",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [2] )
),
New Column( "B",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Selected,
Set Values( [1] )
)
);
If( Try( dt:c << get name, "" ) == "",
type = "character";
formula = "\!"missing column\!"";
,
type = "numeric/continuous";
formula = ":Name(\!"C\!") - :Name(\!"B\!")";
);
Eval(
Parse(
"dt << new column(\!"value\!"," || type || ", Formula(" || formula
|| "))"
)
);