Filtrar una tabla de datos con una aplicación de filtrado personalizadaHola a todos,
Estoy creando una aplicación/panel de control con varios informes dentro. Al final, me gustaría darles a los usuarios la opción de hacer una "consulta" de la tabla de datos principal y guardarla si la necesitan más adelante.
Actualmente, tengo un botón que abre otra ventana y solicita al usuario que seleccione columnas de filtrado (de una lista preseleccionada).
Una vez que los seleccionan, presionan otro botón que debería crear un cuadro de lista para cada una de las columnas de filtrado con todos los valores distintos disponibles. Mi idea es que, a partir de aquí, el usuario seleccione los valores para los que desea que se realice el filtrado en cada cuadro de lista y luego presione un botón final para guardar esos valores y luego se creará una cláusula de filtro/donde que creará un subconjunto de la tabla de datos principal y la guardará en una ubicación conocida.
Creo que estoy a mitad de camino. Conseguí que funcionaran la primera ventana y la selección de la columna de filtro. Luego, puedo mostrar los valores en cuadros de lista, pero no puedo crear el botón correcto para guardar los valores seleccionados. Además, creo que me estoy encontrando con el problema de no saber cuántas columnas de filtro crearán los usuarios, por lo tanto, tengo que tener una expresión para definir una cantidad desconocida de columnas. Vi algunos ejemplos con declaraciones Eval(Parse(Eval Into, pero aún no lo he entendido.
Cualquier ayuda será bienvenida. Quizás haya una manera mucho más sencilla de hacerlo.
Aquí está parte del código que tengo hasta ahora.
filter_col_append_expr = Expr(
lub1 << Append(List Box(column(dt1,Char(col_filter[count_i])) <<GETASMATRIX></GETASMATRIX>
//The button which will run the whole thing is here. Some code is ommited
Panel Box("Database Query", Button Box("Query",query_expr;query_window << Append(bb3 = Button Box("Select Filter Values",query_values = lub1<<GET selected=""></GET><BR /><LINGO-LABS id="lingo-labs-828278" slang="en-US" mode="CREATE"><LINGO-LABEL>Automatización y scripting</LINGO-LABEL><LINGO-LABEL>Exploración y visualización de datos</LINGO-LABEL><LINGO-LABEL>Ventanas</LINGO-LABEL></LINGO-LABS>Re: Filtrar una tabla de datos con una aplicación de filtrado personalizada¿Ha considerado crear un filtro de datos basado en las columnas seleccionadas por el usuario?
Re: Filtrar una tabla de datos con una aplicación de filtrado personalizadaSí, pero cuanto menos desorden, mejor, ya que no muchos usuarios son nuevos en JMP y quiero que sea lo más fácil posible para ellos visualizar y con solo presionar un botón obtener sus datos filtrados.
Hacerlo con el filtro local también podría funcionar.
Re: Filtrar una tabla de datos con una aplicación de filtrado personalizadaYo crearía un filtro de datos (que puedes limpiar si es necesario), pero aquí hay una opción para usar cuadros de lista.
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
options = dt << Get Column Names("String");
filter_col_append_expr = Expr(
Summarize(dt, colvals = By(Eval(selection))); // Note that Summarize this will change numeric values to strings
lub1 << Append(List Box(colvals));
);
query_expr = Expr(
query_window = New Window("Database Query",
Spacer Box(size(1, 5)),
vlb3 = V List Box(
Text Box("Select All Filter Columns"),
H List Box(
Spacer Box(size(1, 5)),
lb3 = List Box(
options,
max selected(8)
)
),
Spacer Box(size(1, 10)),
Button Box("Select Filter Columns",
cols = lb3 << get selected;
Try(lub1 << Delete Box());
lub_collector << Append(lub1 = Lineup Box(N Col(4)));
For Each({selection}, cols,
filter_col_append_expr
);
),
lub_collector = V List Box();
)
)
);
//The button which will run the whole thing is here. Some code is ommited
nw = New Window("",
Panel Box("Database Query",
Button Box("Query",
query_expr;
query_window << Append(
bb3 = Button Box("Select Filter Values",
vals = (lub1 << XPath("//ListBoxBox")) << get selected;
user_selections = Associative Array(cols, vals);
show(user_selections);
)
);
)
)
);
Re: Filtrar una tabla de datos con una aplicación de filtrado personalizadaGracias, eso funciona como pretendía.
Sin embargo, en el siguiente paso estoy un poco estancado.
Para construir el filtro de datos estaba pensando en poner directamente el array asociado con las selecciones del usuario pero eso no está funcionando.
Luego pensé en dividir eso en el filtro de datos y usar Expr y otros comandos de cadena para construirlo para que se vea exactamente como si hubiera usado el triángulo rojo después de construir un filtro de datos interactivo, pero creo que me estoy equivocando en algún lugar de la sintaxis.
Este es mi código de su ejemplo de BigClass
where_clause_list = {};
where_clause = "";
keys = user_selections << getkeys;
values = user_selections << getvalues;
For ( i=1, i<=NItems(keys), i++,
// Inner loop iterating over items for each category
For Each( {value}, values[i],
// Action for each category-item pair
(where_clause = where_clause || ":"||keys[i] || " ==" || " " || Char(value) || " &"|| " ");
InsertInto(where_clause_list, where_clause);
where_clause = "";));
where_clause="";
For Each({where},where_clause_list,where_clause=where_clause||where);
where_clause = Left(where_clause,Length(where_clause) -3);
Show(where_clause_list);
Show(where_clause);
where_expr = Expr(where_clause);
key_clause="";
For Each({key},keys,key_clause=key_clause||"Ascolumn("||key||")"||" ,");
key_clause = Left(key_clause,Length(key_clause) -2);
keys_expr=Expr(key_clause);
Show(key_clause);
dt << Data Filter(Add Filter(columns(key_expr),Where(where_expr),
Mode( Select( 0 ), Show( 1 ), Include( 1 ))));
Pero ¿existe una forma más directa e intuitiva de hacerlo?
Re: Filtrar una tabla de datos con una aplicación de filtrado personalizadaSi ya tiene las selecciones en una matriz asociativa, ¿necesita más el filtro de datos? Mi sugerencia anterior de usar el filtro de datos era evitar la creación de cuadros de lista "adicionales" para seleccionar valores de fila.
Re: Filtrar una tabla de datos con una aplicación de filtrado personalizadaUna vez que tengo las selecciones (tanto los nombres de las columnas como los valores), quería crear un subconjunto de los datos y extraer solo lo que se filtra según las selecciones del usuario. Para eso necesitaría algún filtro de datos, ¿no?
Re: Filtrar una tabla de datos con una aplicación de filtrado personalizadaDependiendo de lo que quieras decir con "extraer", puedes usar << Obtener filas donde + Subconjunto o << Seleccionar donde + Subconjunto o << Seleccionar donde + Ocultar y excluir
Re: Filtrar una tabla de datos con una aplicación de filtrado personalizadaSí, exactamente. Quería usar algunos de esos métodos, pero no estaba seguro de cómo hacerlo cuando no sé qué columna y qué valores ha seleccionado el usuario. Las selecciones ahora están en una matriz asociativa, pero traducirlas a una cláusula Where fue la dificultad para mí. Es por eso que intenté construir la cláusula Where con el fragmento de código anterior que mostré, pero no lo logré. Tal vez haya una forma más sencilla de trabajar con la matriz asociativa para construir la cláusula Where.
Re: Filtrar una tabla de datos con una aplicación de filtrado personalizadaLa opción más sencilla sería utilizar directamente el filtro de datos, pero ya lo hemos descartado. ¿Las selecciones del usuario se deben combinar mediante AND o OR?
Re: Filtrar una tabla de datos con una aplicación de filtrado personalizadaAquí hay algunas opciones
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
// Build using Select Where (simplest)
// Note that we convert to Char due to using Summary and because we can have numeric values
// This could (and should) be handled earlier in some other method
user_selections = ["age" => {"13", "14"}, "sex" => {"F"}];
For Each({{col, values}, idx}, user_selections,
If(idx == 1,
dt << Select Where(Contains(values, Char(Column(dt, col)[])));
);
dt << Select Where(Contains(values, Char(Column(dt, col)[])), Current Selection("restrict")); // AND
// dt << Select Where(Contains(values, Char(Column(dt, col)[])), Current Selection("extend")); // OR
);
show(dt << get selected rows);
wait(1); // demo purposes
dt << Clear Select;
// A bit more complicated is to build expression and use that
user_selections = ["age" => {13, 14}, "sex" => {"F"}]; // simplified to use numeric value for numeric column
filter_expr = Expr(And()); // optionally use Or()
For Each({{col, values}, idx}, user_selections,
cur_expr = Substitute(
Expr(Contains(_list_, _column_)),
Expr(_list_), values,
Expr(_column_), Name Expr(AsColumn(dt, col))
);
Insert Into(filter_expr, Name Expr(cur_expr));
);
// Show(Name Expr(filter_expr));
my_rows = dt << Get Rows Where(filter_expr);
show(my_rows);