Vorrei catturare errori quando una formula contiene una colonna mancante. Nell'esempio seguente, una tabella contiene 2 colonne. Aggiungendo una nuova colonna che utilizza una colonna inesistente, il risultato è un risultato mancante (correttamente) e un errore che blocca il mio script che non sono in grado di catturare perché l'istruzione try non funziona. Esiste una soluzione alternativa per questo?
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";
);
Non sono esattamente sicuro di quale sia il risultato finale, se manca la colonna, ma il seguente è un modo per gestire il 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
|| "))"
)
);Grazie, ma non è così utile. Il problema è che estraggo automaticamente alcuni dati (tramite script) e alcuni di essi possono mancare (ma non so in anticipo se e quali). Lo script si interrompe quando viene trovata la colonna mancante e questo è il vero problema. Una buona soluzione potrebbe essere l'istruzione try, ma non funziona.
Potrebbe essere meglio testare prima di creare la colonna della formula. Quindi fai un'istruzione if per vedere se la colonna esiste ... in caso contrario, non creare la colonna della formula.
@antonio-domenico , credo che quello che vuoi sia determinare, prima di provare a creare una colonna basata su una formula, se la tabella contiene le colonne appropriate per la formula data?Se sei in grado di determinarlo prima di provare a creare la colonna, avrai meno probabilità di incappare in errori di arresto dello script.
La buona notizia è che è abbastanza semplice determinare tutti i nomi esterni su cui si basa una formula, che dovrebbero essere solo i nomi delle colonne della tabella di dati corrente.(È consigliabile non fare in modo che una formula si basi su una variabile attualmente nell'ambito che perderà l'ambito a un certo punto in futuro, causando errori nella formula).
Ecco un esempio di codice con una funzione che analizza ricorsivamente le espressioni (le formule sono ovviamente solo espressioni) per qualsiasi nome penzolante.È quindi possibile controllare i nomi delle colonne della tabella e applicare se i nomi delle colonne soddisfano la formula:
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>Fatemi sapere se avete domande!
Giordania,