Sie sind auf Seite 1von 12

Navegando Datos Usando Arboles

En esta entrada vamos a ver como introducir un control de tipo rbol en las paginas de Peoplesoft.
Anteriormente para cumplir este requerimiento el Application Designer provea un control llamado
tree. En la ltimas versiones de las PeopleTools se recomienda no usar ms este control, en
cambio Peoplecode posee una funcin llamada GenerateTree que permite cargar los rboles en un
control de tipo HTML Area.

En los peoplebooks se encuentra un ejemplo de como cargar los rboles creados por el gestor de
rboles en una pgina creada por nosotros. La ruta del ejemplo en los PeopleBooks
es Home > PeopleBooks > Enterprise PeopleTools 8.51 PeopleBook: PeopleCode Developer's
Guide > Using HTML Trees and the GenerateTree Function.
El ejemplo que vamos a describir en esta entrada nos permitir crear un rbol a partir de cualquier
estructura jerrquica que se cree dentro de peoplesoft.
El primer paso es crear nuestra estructura jerarquica, para eso creamos un componente que
permita insertar los empleados de una organizacin de tal forma que estn relacionados con su
jefe.
A continuacin podemos ver la estructura del registro PE_TREE_EMPLE que vamos a utilizar para
ingresar la estructura jerrquica de los empleados.

Luego creamos la pgina PE_TREE_EMPLEADOS para administrar los datos del registro
PE_TREE_EMPLE. La pgina debe verse como se muestra a continuacin

Luego creamos un componente con registro de bsqueda INSTALLATION y un men que nos
permita registrar el componente dentro del portal.
En nuestro nuevo componente ingresamos unos datos de prueba como se ven en la ilustracin:

El siguiente paso es crear un Application Package que nos permita administrar los datos ingresado
por el componente PE_TREE_EMPLEADOS en forma de nodos de un rbol. Para lo anterior
crearemos la clase es pe_nodoEmpleado dentro del paquete PE_TREE_EMPLEADOS. Est clase
nos permitir manejar como un nodo cada uno de los registros ingresados por el componente
PE_TREE_EMPLEADOS. La clase tambin poseer un arreglo de objetos de est misma clase
que
representar
los
hijos
del
nodo.

A continuacin podemos ver el cdigo completo de la clase descrito lnea por lnea.
/*Lo primero es declarar nuestra clase*/

class pe_nodoEmpleado
/*El mtodo constructor recibir compo parmetros el nombre del nodo (En
nuestro caso el nombre del nodo ser el id del empleado que se creo), la
descripcin (El nombre del empleado que se creo) y un indicador que
indica si el nodo raz del rbol o no*/
method pe_nodoEmpleado(&str_nombreNodo_par As string,
&str_descNodo_par As string, &bol_nodoRaiz_par As boolean);
/*El siguiente mtodo permite cargar los hijos del nodo actual en un
arreglo */
method pe_cargarHijos();
/*El mtodo getNodo permite retornar un nodo que se encuentre dentro de
la estructura de nodos que se est procesando. */
method pe_getNodo(&str_nombreNodo_par As string) Returns
PE_TREE_EMPLEADOS:pe_nodoEmpleado;
/*El mtodo getNodo permite retornar un nodo que se encuentre dentro de
la estructura de nodos que se est procesando. */
method pe_getNodoNumber(&nbr_idNodo As number) Returns
PE_TREE_EMPLEADOS:pe_nodoEmpleado;
/*Mtodo que retorna el total de hijos del nodo*/
method pe_totalHijos() Returns number;
/*Propiedad para consultar el nombre del nodo*/
property string NOMBRE_NODO get;
/*Propiedad

para

consultar

la

descripcin

del

nodo*/

property string DESCR_NODO get;


/*Propiedad

que

indica

si

ya

fueron

cargados

los

nodos

hijos*/

property boolean CARGO_HIJOS get;


/*Propiedad

que

indica

si

el

nodo

tiene

hijos

property boolean TIENE_HIJOS get;


/*Propiedad que indica si el nodo es el nodo raz de la estructura */
property boolean NODO_RAIZ get;
private
/*variable para almacenar el nombre del nodo*/

no*/

instance string &str_nombreNodo;


/*variable para almacenar la descripcin del nodo*/
instance string &str_descNodo;
/*variable para almacenar si ya se cargaron los hijos*/
instance boolean &bol_cargoHijos;
/*variable para almacenar si el nodo es el nodo raz*/
instance boolean &bol_nodoRaiz;
/*variable para almacenar el listado de nodos hijos del nodo actual*/
instance array of PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_hijos;
end-class;
method pe_nodoEmpleado
/+ &str_nombreNodo_par as String, +/
/+ &str_descNodo_par as String, +/
/+ &bol_nodoRaiz_par as Boolean +/
/*Se inicializan las variables privadas de la clase*/
&str_nombreNodo = &str_nombreNodo_par;
&str_descNodo = &str_descNodo_par;
&bol_cargoHijos = False;
&bol_nodoRaiz = &bol_nodoRaiz_par;
end-method;
method pe_cargarHijos
/*Se inicializa el arreglo &obj_hijos en el que se almacenarn los nodos
hijos del nodo actual*/
Local PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_hijo = create
PE_TREE_EMPLEADOS:pe_nodoEmpleado(" ", " ", False);
Local string &str_cod, &str_nombre;
Local SQL &sql_hijos;
&obj_hijos = CreateArrayRept(&obj_hijo, 0);
/*Si el nodo actual est marcado como el nodo raz entonces se cargan
todos los empleados que no tengan ningn jefe*/
If &bol_nodoRaiz Then
&sql_hijos = CreateSQL("SELECT PE_CODIGO_EMPL, PE_NOMBRE_EMPLEADO
FROM PS_PE_TREE_EMPLE WHERE PE_CODIGO_JEFE = ' '");
Else
/*Si el nodo actual no es el nodo raz se cargan todos los empleados cuyo
jefe sea el nodo actual*/
&sql_hijos = CreateSQL("SELECT PE_CODIGO_EMPL, PE_NOMBRE_EMPLEADO
FROM PS_PE_TREE_EMPLE WHERE PE_CODIGO_JEFE = :1", &str_nombreNodo);
End-If;

/*Para cada uno de los empleados hijos del nodo actual, se crear un
nodo y se agrega al arreglo de nodos hijos del nodo actual*/
While &sql_hijos.Fetch(&str_cod, &str_nombre)
&obj_hijo = create PE_TREE_EMPLEADOS:pe_nodoEmpleado(&str_cod,
&str_nombre, False);
&obj_hijos.Push(&obj_hijo);
End-While;
/*Se marca el nodo para que indique que ya fueron cargados los nodos*/
&bol_cargoHijos = True;
end-method;
get NOMBRE_NODO
/+ Returns String +/
Return &str_nombreNodo;
end-get;
get DESCR_NODO
/+ Returns String +/
Return &str_descNodo;
end-get;
get CARGO_HIJOS
/+ Returns Boolean +/;
Return &bol_cargoHijos;
end-get;

get TIENE_HIJOS
/+ Returns Boolean +/;
Local number &nbr_hijos = 0;
/*si ya fueron cargados los hijos se valida que el arreglo de nodos hijos
tenga hijos*/
If &bol_cargoHijos Then
If &obj_hijos.Len = 0 Then
Return False;
Else
Return True;
End-If;
Else
/*Si no han sido cargados los hijos se
para verificar si tienes nodos hijos*/
If &bol_nodoRaiz Then
SQLExec("select count(1) from
PE_CODIGO_JEFE = ' '", &nbr_hijos);
Else
SQLExec("select count(1) from
PE_CODIGO_JEFE = :1", &str_nombreNodo,
End-If;
If &nbr_hijos = 0 Then
Return False;

consulta la tabla de empleados


ps_PE_TREE_EMPLE where
ps_PE_TREE_EMPLE where
&nbr_hijos);

Else
Return True;
End-If;
End-If;
end-get;
get NODO_RAIZ
/+ Returns Boolean +/
Return &bol_nodoRaiz
end-get;
method pe_getNodo
/+ &str_nombreNodo_par as String +/
/+ Returns PE_TREE_EMPLEADOS:pe_nodoEmpleado +/
Local number &nbr_nodos;
Local PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_hijo;
/*Retorna el nodo buscado, si es el actual, si es algn nodo hijo o si
es algn nodo hijo de los nodos hijos del nodo actual*/
If &str_nombreNodo_par = &str_nombreNodo Then
Return %This;
Else
If &bol_cargoHijos Then
For &nbr_nodos = 1 To &obj_hijos.Len
If &str_nombreNodo_par = &obj_hijos [&nbr_nodos].NOMBRE_NODO
Then
Return &obj_hijos [&nbr_nodos];
Else
&obj_hijo = &obj_hijos
[&nbr_nodos].pe_getNodo(&str_nombreNodo_par);
If &obj_hijo <> Null Then
Return &obj_hijo;
End-If;
End-If;
End-For;
Return Null
Else
Return Null;
End-If;
End-If;
end-method;
method pe_getNodoNumber
/+ &nbr_idNodo as Number +/
/+ Returns PE_TREE_EMPLEADOS:pe_nodoEmpleado +/
Return &obj_hijos [&nbr_idNodo];
end-method;
method pe_totalHijos
/+ Returns Number +/
Return &obj_hijos.Len;
end-method;

Con algunas modificaciones a la clase anterior se puede tener una clase que administre cualquier
tabla que almacene una estructura jerrquica.
La funcin GenerateTree funciona utilizando
generacin del rbol y otro que contiene cada
registro lo llamaremos PE_TREE_HDR
TREECTL_HDR_SBR y el segundo registro
utilizando el subrecord TREECTL_NDE_SBR.

2 records, uno que almacena los


uno de los nodos que pertenecen al
y se debe crear utilizando
los llamaremos PE_TREE_NDE y

parmetros de
rbol. El primer
el subrecord
se debe crear

El siguiente paso en nuestro ejemplo es crear un registro derived que almacene el campo tipo
LONG que tendr el cdigo HTML que generar la funcin GenerateTree y el campo Char(50) que
controlar los eventos que se generen en el HTML creado por la funcin GenerateTree.
En la siguiente imagen se puede ver la estructura de los 4 registro que estamos utilizando en
nuestro proyecto.

El siguiente paso es crear la pgina PE_TREE_EXAMPLE en la cual mostraremos el rbol de


empleados. A la pgina se le debe agregar un objeto HTMLAREA asociado al campo
HTML_AREA_01 del registro PE_TREE_EXP. Tambin se debe agregar un Editbox asociado al
campo PE_EVENT_FIELD del registro PE_TREE_EXP que debe ser invisible, debe tener marcada
la propiedad Modifiable by JavaScript y en la propiedad Page Field Name debe tener
PE_EVENT_FIELD.
La pgina debemos agregarla a un componente cuyo registro de bsqueda sea
INSTALLATION. El componente lo llamamos PE_TREE_EXAMPLE y se debe registrar en el portal
para poder acceder a la pgina.
En el evento PostBuild del componente debemos agregar el cdigo que inicializa nuestro rbol. A
continuacin se lista el cdigo que debe ir en el postbuild:

/*Se importa la clase que creamos para administrar los nodos del rbol de
empleados*/
import PE_TREE_EMPLEADOS:pe_nodoEmpleado;
/*Declaramos la variable que tendr el nodo raz de nuestro rbol*/
Component PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_nodos;
/*Declaramos el rowset que contendr la estructura que se utilizar para
ejecutar la funcin GenerateTree*/
Component Rowset &TREECTL;
&NODE_ROWSET = CreateRowset(Record.PE_TREE_NDE);
&TREECTL = CreateRowset(Record.PE_TREE_HDR, &NODE_ROWSET);
&TREECTL.InsertRow(1);
&REC = &TREECTL.GetRow(2).GetRecord(1);
/* Set the HDR options:
/*Asignamos el nombre de la pgina en la que va a ser mostrado el rbol*/
&REC.GetField(Field.PAGE_NAME).Value = "PE_TREE_EXAMPLE";
/*Asignamos el nombre del campo que usaremos para controlar los eventos
generados en el rbol*/
&REC.GetField(Field.PAGE_FIELD_NAME).Value = "PE_EVENT_FIELD";
/*Los siguientes campos se asignan por defecto*/
&REC.GetField(Field.PAGE_SIZE).Value = 15;
&REC.GetField(Field.DISPLAY_LEVELS).Value = 8;
&REC.GetField(Field.COLLAPSED_IMAGE).Value = "PT_TREE_COLLAPSED";
&REC.GetField(Field.EXPANDED_IMAGE).Value = "PT_TREE_EXPANDED";
&REC.GetField(Field.END_NODE_IMAGE).Value = "PT_TREE_END_NODE";
&REC.GetField(Field.LEAF_IMAGE).Value = "PT_TREE_LEAF";
&REC.GetField(Field.IMAGE_WIDTH).Value = 15;
&REC.GetField(Field.IMAGE_HEIGHT).Value = 12;
&REC.GetField(Field.INDENT_PIXELS).Value = 20;
/*Se crea el nodo raz de nuestro rbol de empleados*/
&obj_nodos = create PE_TREE_EMPLEADOS:pe_nodoEmpleado("Empleados", "Todos
los Empleados", True);
/*Si el nodo tiene hijos en la variable &PARENT_FLAG X que indica que el
nodo tiene hijos y no estos no se han desplegado*/
If &obj_nodos.TIENE_HIJOS Then
&PARENT_FLAG = "X";
Else
&PARENT_FLAG = "Y";

End-If;
&NODE_ROWSET = &TREECTL.GetRow(2).GetRowset(1);
&NODE_ROWSET.InsertRow(1);
&REC = &NODE_ROWSET.GetRow(2).GetRecord(1);
/*Se le indica al nodo que no es una hoja*/
&REC.GetField(Field.LEAF_FLAG).Value = "N";
/*Se asigna el nombre del nodo*/
&REC.GetField(Field.TREE_NODE).Value = "Empleados";
/*Se asigna la descripcin del nodo*/
&REC.GetField(Field.DESCR).Value = "Todos los Empleados";
/*Se asignan los siguiente valores por defecto*/
&REC.GetField(Field.RANGE_FROM).Value = "";
&REC.GetField(Field.RANGE_TO).Value = "";
&REC.GetField(Field.DYNAMIC_FLAG).Value = "N";
&REC.GetField(Field.ACTIVE_FLAG).Value = "Y";
&REC.GetField(Field.DISPLAY_OPTION).Value = "B";
&REC.GetField(Field.STYLECLASSNAME).Value = "PSHYPERLINK";
/*Se asigna el valor de la variable PARENT_FLAG*/
&REC.GetField(Field.PARENT_FLAG).Value = &PARENT_FLAG;
/*Se indica que el nodo est a nivel 1 dentro del rbol*/
&REC.GetField(Field.TREE_LEVEL_NUM).Value = 1;
&REC.GetField(Field.LEVEL_OFFSET).Value = 0;
/*Se ejecuta la funcin GenerateTree y el resultado se asigna al control
HTMLAREA que agregamos a la pgina */
PE_TREE_EXP.HTML_AREA_01 = GenerateTree(&TREECTL);

El ltimo paso de nuestro ejemplo es agregar el cdigo necesario al evento FieldChange del
campo PE_TREE_EXP.PE_FIELD_EVENT. El cdigo que agregaremos a este evento controla
cuando se despliegan o se colapsan los nodos y la carga de los nodos hijos cada vez que sea
necesario.
/*Se importa la clase para administrar los nodos de empelados*/
import PE_TREE_EMPLEADOS:pe_nodoEmpleado;
/*Se declara el rowset que contiene la informacin de los nodos que sern
generados por la funcin GenerateTree*/
Component Rowset &TREECTL;

/*Se declara el objeto que contiene el nodo raz del rbol de empleados*/
Component PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_nodos, &obj_nodoActual;
Local PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_nodoActual, &obj_Hijo;
/*Si el evento es de despliegue de un nodo*/
If Left(PE_TREE_EXP.PE_EVENT_FIELD, 1) = "X" Then
/*Se obtiene la fila que representa el nodo sobre el cual fue ejecutado
el evento*/
&ROW = Value(Right(PE_TREE_EXP.PE_EVENT_FIELD,
Len(PE_TREE_EXP.PE_EVENT_FIELD) - 1)) + 1;
&NODE_ROWSET = &TREECTL.GetRow(2).GetRowset(1);
/*Se obtiene el registro que corresponde al nodo sobre el que se ejecut
el evento*/
&PARENT_REC = &NODE_ROWSET.GetRow(&ROW).GetRecord(1);
/*Se valida el nivel del nodo sobre el que se ejecuto el evento */
&PARENT_LEVEL = &PARENT_REC.GetField(Field.TREE_LEVEL_NUM).Value;
&ROW = &ROW + 1;
/*Se obtiene el objeto nodo que corresponde al nodo del rbol sobre el
que se ejecuto el evento*/
&obj_nodoActual =
&obj_nodos.pe_getNodo(&PARENT_REC.GetField(Field.TREE_NODE).Value);
/*Si el nodo tiene hijos se cargan los hijos al rbol*/
If &obj_nodoActual.TIENE_HIJOS Then
&obj_nodoActual.pe_cargarHijos();
Local number &nbr_nodos;
/*Se recorren los hijos del nodo y se agregan al rowset que se est
usando de base para el rbol*/
For &nbr_nodos = 1 To &obj_nodoActual.pe_totalHijos()
&obj_Hijo = &obj_nodoActual.pe_getNodoNumber(&nbr_nodos);
&LEVEL_OFFSET = 0;
&NODE_ROWSET.InsertRow(&ROW - 1);
&REC = &NODE_ROWSET.GetRow(&ROW).GetRecord(1);
If &obj_Hijo.TIENE_HIJOS Then
&PARENT_FLAG = "X";
&REC.GetField(Field.LEAF_FLAG).Value = "N";
&REC.GetField(Field.TREE_NODE).Value = &obj_Hijo.NOMBRE_NODO;
&REC.GetField(Field.DESCR).Value = &obj_Hijo.DESCR_NODO;
&REC.GetField(Field.RANGE_FROM).Value = "";
&REC.GetField(Field.RANGE_TO).Value = "";
Else
/*Si el nodo no tiene hijos se marca como una hoja para diferenciarlo en
el rbol */
&PARENT_FLAG = "N";
&REC.GetField(Field.LEAF_FLAG).Value = "Y";
&REC.GetField(Field.TREE_NODE).Value = " ";

&REC.GetField(Field.DESCR).Value = " ";


&REC.GetField(Field.RANGE_FROM).Value =
&obj_Hijo.NOMBRE_NODO;
&REC.GetField(Field.RANGE_TO).Value = &obj_Hijo.DESCR_NODO;
End-If;
&REC.GetField(Field.DYNAMIC_FLAG).Value = "N";
&REC.GetField(Field.ACTIVE_FLAG).Value = "Y";
&REC.GetField(Field.DISPLAY_OPTION).Value = "B";
&REC.GetField(Field.STYLECLASSNAME).Value = "PSHYPERLINK";
&REC.GetField(Field.PARENT_FLAG).Value = &PARENT_FLAG;
&REC.GetField(Field.TREE_LEVEL_NUM).Value = &PARENT_LEVEL + 1;
&REC.GetField(Field.LEVEL_OFFSET).Value = &LEVEL_OFFSET;
&ROW = &ROW + 1;
End-For;
/* Se indica al nodo actual que ya se cargaron los nodos*/
&PARENT_REC.GetField(Field.PARENT_FLAG).Value = "Y";
End-If;
Else
/* Se procesa el evento de seleccin de un nodo*/
If Left(PE_TREE_EXP.PE_EVENT_FIELD, 1) = "S" Then
Local number &nbr_filas;
/*Se recupera el id del nodo sobre el cual se genero el evento*/
&ROW = Value(Right(PE_TREE_EXP.PE_EVENT_FIELD,
Len(PE_TREE_EXP.PE_EVENT_FIELD) - 1)) + 1;
&NODE_ROWSET = &TREECTL.GetRow(2).GetRowset(1);
/* se marca como no seleccionado el nodo que haba sido seleccionado
previamente*/
For &nbr_filas = 1 To &NODE_ROWSET.ActiveRowCount
&REC = &NODE_ROWSET.GetRow(&nbr_filas).GetRecord(1);
If &REC.STYLECLASSNAME.value = "PSTREENODESELECTED" Then
&REC.STYLECLASSNAME.value = "PSHYPERLINK";
End-If;
End-For;
&REC = &NODE_ROWSET.GetRow(&ROW).GetRecord(1);
/*Se marca el nodo seleccionado como seleccionado*/
&REC.STYLECLASSNAME.value = "PSTREENODESELECTED";
Else
rem Procesa los eventos adicionales;
End-If;
End-If;

/*Se ejecuta nuevamente la funcin GenerateTree para actualizar el estado


del rbol*/
PE_TREE_EXP.HTML_AREA_01 = GenerateTree(&TREECTL,
PE_TREE_EXP.PE_EVENT_FIELD);
PE_TREE_EXP.PE_EVENT_FIELD = "";

Con el cdigo anterior finalizamos el desarrollo de nuestro proyecto,


podemos ver el resultado.

en la imagen siguiente

Das könnte Ihnen auch gefallen