viernes, 17 de abril de 2009

Formas de cargar un List Item por código

Directamente desde una sql

El proceso se basa en un grupo de registros que creamos en base a una sql dinámica "v_grupo := Create_Group_From_Query('RecorG', v_sql);", para cargar la lista de elementos en base al grupo usamos la instrucción "POPULATE_LIST".

Cuando creamos el ítem del bloque podemos dejarlo sin ningún valor, pero nos va a dar una advertencia de compilación un poco molesta, pero totalmente inocua. Si queremos que no nos dé, simplemente abrimos los elementos de lista y en el primer elemento le quitamos el campo "Valor de elemento de Lista" y como el valor por inicial es NULL y ese elemento es NULL no nos va a protestar.

Ejemplo:

DECLARE
v_sql VARCHAR2(200); -- Variable para construir la SELECT dinánica.
v_grupo RecordGroup; -- Variable en donde vamos a meter el grupo de registros temporalmente.
v_estado_empresa ESTADOS.CODIGO%TYPE := 'ESPA'; -- Variable que contiene el valor que queremos mostrar por defecto.
BEGIN
/*
Construimos la SELECT. En el primer campo sacamos
lo que queremos que muestre la lista y en el segundo
campo el valor correspondiente que va a devolver
por la selección (normalmente un código).
*/

v_sql := 'SELECT INITCAP(nombre), codigo FROM estados ORDER BY nombre';


-- Asignamos el resultado de la select al grupo de registros.
v_grupo := Create_Group_From_Query('RecorG', v_sql);

-- Construimos la lista, siempre y cuando la select devolviese registros.
IF POPULATE_GROUP(v_grupo) = 0 THEN
POPULATE_LIST('B1.ESTADO', V_Grupo);
END IF;

-- Borramos el grupo, liberamos memoria que ya no nos hace falta.
DELETE_GROUP(v_grupo);

-- Asignamos el valor por defecto que queremos.
:b1.estado := v_estado_empresa;

-- Si el campo es obligatorio deberíamos de poner esto para que nos elimine el elemento en blanco.
Set_Item_Property('B1.ESTADO', REQUIRED, PROPERTY_TRUE);
END;


Elemento a elemento

Para limpiar un List-item se hace con la instrucción CLEAR_LIST('BLOQUE.CAMPO');

Para ir añadiendo elementos se hace con ADD_LIST_ELEMENT('BLOQUE.CAMPO', , , );

* : Será un número que identifica cada elemento, se comenzará a numerar en el 1.
* : Texto que visualizará en el desplegable el usuario.
* : Valor que toma el campo cuando se selecciona.


Ejemplo:


DECLARE
CURSOR cur_clientes IS
SELECT codigo_rapido, nombre
FROM clientes;

v_indice NUMBER;
v_primer_cliente CLIENTES.CODIGO_RAPIDO%TYPE;
BEGIN
Set_Item_Property('B1.CLIENTE', REQUIRED, PROPERTY_FALSE);
CLEAR_LIST('B1.CLIENTE');

FOR reg IN cur_clientes LOOP
v_indice := v_indice + 1;
Add_List_Element('B1.CLIENTE', v_indice, reg.nombre, reg.codigo_rapido);

IF v_primer_cliente IS NULL THEN
v_primer_cliente := reg.codigo_rapidol;
END IF;
END LOOP;
:b1.cliente := v_primer_cliente;
Set_Item_Property('B1.CLIENTE', REQUIRED, PROPERTY_TRUE);
END;


11 comentarios:

Anna dijo...

Hola, el código me fue muy útil. Yo lo uso con RefCursors y me salen muy bien, el problema que tengo es que el último registro se duplica, podrían indicarme qué es lo que puede estar pasando?

No es el select el que me trae el registro duplicado.

Probé poner un alert en el loop cuando se va cargando el list y tampoco veo que traiga duplicado el último registro.

Por favor, si pueden ayudarme se los voy a agradecer mucho, porque tengo varios list y en todos me pasa lo mismo.

Saludos

sailefm dijo...

Mánda un ejemplo del código que utilizas.

Anna dijo...

Hola, te paso el código que utilizo:

PROCEDURE COMBO_PERSONAS (nom_combo VARCHAR2) IS


TYPE t_registro IS RECORD (cdpersona TPERSONA.cdpersona%TYPE,
nombre TPERSONA.nombre%TYPE);
registro t_registro;

TYPE cursor_registros IS REF CURSOR;



PV_REGISTRO_O cursor_registros;


nRow NUMBER :=0;
BEGIN

Set_Item_Property(nom_combo, REQUIRED, PROPERTY_FALSE);
CLEAR_LIST(nom_combo);


PKG_DATOS_PERS.P_PERSONAS ( PV_REGISTRO_O );

LOOP
FETCH PV_REGISTRO_O INTO registro;

nRow := nRow +1;
Add_List_Element(nom_combo, nRow, registro.nombre, registro.cdpersona);

EXIT WHEN PV_REGISTRO_O%NOTFOUND;
END LOOP;

Set_Item_Property(nom_combo, REQUIRED, PROPERTY_TRUE);

Exception
When Others then
Message('Ocurrio el siguiente error ' || SQLERRM);


END;

Muchas gracias
Saludos

sailefm dijo...

El fallo es que realmente estas metiendo el último registro dos veces, deberías poner el EXIT WHEN PV_REGISTRO_O%NOTFOUND; justo después del FETCH:

PROCEDURE COMBO_PERSONAS (nom_combo VARCHAR2) IS


TYPE t_registro IS RECORD (cdpersona TPERSONA.cdpersona%TYPE,
nombre TPERSONA.nombre%TYPE);
registro t_registro;

TYPE cursor_registros IS REF CURSOR;



PV_REGISTRO_O cursor_registros;


nRow NUMBER :=0;
BEGIN

Set_Item_Property(nom_combo, REQUIRED, PROPERTY_FALSE);
CLEAR_LIST(nom_combo);


PKG_DATOS_PERS.P_PERSONAS ( PV_REGISTRO_O );

LOOP
FETCH PV_REGISTRO_O INTO registro;
EXIT WHEN PV_REGISTRO_O%NOTFOUND;

nRow := nRow +1;
Add_List_Element(nom_combo, nRow, registro.nombre, registro.cdpersona);
END LOOP;

Set_Item_Property(nom_combo, REQUIRED, PROPERTY_TRUE);

Exception
When Others then
Message('Ocurrio el siguiente error ' || SQLERRM);


END;

Anna dijo...

Muchas gracias sailfem! Realmente me salvaste la vida! jajaj

Ahora se ven perfectos mis combos!

Saludos

Iveive dijo...

Hola, hice el record group, funciona super bien. pero cuando hago F7(enter query) F8 (execute query) en el bloque para revisar la data que ingrese, no me trae informacion porque al parecer se valida contra la lista, y como el campo esta en blanco pues me sale el mensaje de que no se consiguen registros. :( como resuelvo este problema?

sailefm dijo...

En Forms si cargas un LIST-ITEM de un campo asociado a tabla, cuando ejecutas consulta si el valor del campo no se corresponde con ningún elemento del list-item el registro no se muestra.

Por ejemplo:

Si en la tabla tienes los siguientes registros:

registro 1: A
registro 2: B
registro 3: C
registro 4: D

y el list-item únicamente tiene los valores C y D los registros 1 y 2 no se visualizarán.

MarioER dijo...

buen ejemplo me servio de mucho
gracias

Erika dijo...

Justamente tengo ese error en un formulario, al cargar un registro con un dato que no esta en la lista el registro entero no se muestra, ¿como solucionas ese problema?

sailefm dijo...

Puedes usar la propiedad "Correspondencia con otros valores", de forma que ahí puedes indicar si tienes un valor que no está dentro de los elementos del list-item con qué valor de los posibles del list-item lo asocias.

También podrías usar un recuadro combinado, en el caso de que no exista el valor en los elementos posibles del list-item pondría ese valor directamente en el list-item.

Francisco Javier Rincon dijo...

Estas listas se cargan normalmente desde el disparador When-New-Form-Instance a nivel de la forma, sin embargo no se ejecuta desde ningún otro, como puedo ejecutar una lista de este tipo, desde un trigger como WHEN-NEW-ITEM-INSTANCE dado que necesito cambiar la lista de acuerdo a un valor en el bloque...¿alguna idea?