Detectaría errores cuando una fórmula contiene una columna faltante. En el siguiente ejemplo, una tabla contiene 2 columnas. Al agregar una nueva columna que utiliza una columna inexistente, el resultado es un resultado faltante (correctamente) y un error que bloquea mi secuencia de comandos que no puedo detectar porque la declaración try no funciona. ¿Existe una solución alternativa para esto?
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";
);
No estoy exactamente seguro de cuál quiere que sea el resultado final, si falta la columna, pero la siguiente es una forma de manejar el problema
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
|| "))"
)
);Gracias, pero no es tan útil. El problema es que extraigo automáticamente algunos datos (por script) y puede faltar alguno (pero no sé de antemano si y cuáles). El script se detiene cuando se encuentra la columna que falta y este es el verdadero problema. Una buena solución podría ser la declaración de prueba, pero no funciona.
Esto podría ser mejor para probar antes de hacer la columna de fórmula. Así que haga una declaración if para ver si la columna existe... si no existe, no haga la columna de fórmula.
@antonio-domenic , creo que lo que desea es determinar, antes de intentar crear una columna basada en una fórmula, si la tabla contiene las columnas apropiadas para la fórmula dada.Si puede determinar esto antes de intentar crear la columna, tendrá menos probabilidades de encontrarse con errores de detención de secuencias de comandos.
La buena noticia es que es bastante simple determinar todos los nombres externos en los que se basa una fórmula, que deberían ser solo nombres de columna de la tabla de datos actual.(Es una buena práctica no tener una fórmula basada en una variable actualmente dentro del alcance que perderá el alcance en algún momento en el futuro, lo que provocará un error en la fórmula).
Aquí hay un código de ejemplo con una función que analiza expresiones recursivamente (las fórmulas son, por supuesto, solo expresiones) para cualquier nombre pendiente.Luego puede verificar los nombres de las columnas de la tabla y aplicar si los nombres de las columnas cumplen con la fórmula:
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>¡Hazme saber si tienes alguna pregunta!
Jordán,