Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Grid Jerárquico
Message
General information
Forum:
Visual FoxPro
Category:
Other
Miscellaneous
Thread ID:
00698281
Message ID:
00698608
Views:
12
>Buenos dias Martin.
Buenas noches, Mauricio, y disculpa por la demora.

>La verdac es que me dejas bastante intrigado con eso grid que me dices, me gustaria que me enviaras el codigo o el formulario de ejemplo que posees.

Es mi culpa por haber mencionado algo de lo que no tenía un ejemplo sencillo a mano. Es que usamos bastante este recurso, pero cualquiera de los ejemplos era difícil de aislar, ya que debía cambiar el acceso a datos, remover cuestiones del framework, etc.

Finalmente opté por escribir un ejemplo pequeño que te describo. Luego puedo enviarte el formulario por correo, si lo deseas.

Para este ejemplo crea una tabla libre llamada Arbol con esta estructura:
Field  Field Name      Type                Width    Dec   Index   Collate Nulls
    1  NOMBRE          Character              30                             No
    2  CARGO           Character              30                             No
    3  ID              Integer                 4            Asc   Machine    No
    4  REPORTA         Integer                 4            Asc   Machine    No
Y hazle un append from ... delimited con estos datos:
"Juan Fernández","Vendedor",20,17
"Laura Trelles","Vendedor",19,17
"Máximo Carelli","Vendedor",18,17
"Héctor Chiozza","Jefe de Ventas",17,14
"Mabel Arias","Mercadotecnia",16,14
"Anibal Lázaro","Promociones",15,14
"Cecilia Faioli","Gerente de Ventas",14,3
"Ramona Barrales","Jefa de depósito",13,21
"Pedro Echeveste","Encargado de depósito",12,13
"Armando Castro","Encargado de depósito",11,13
"Berta Serrano","Control de Despacho",10,21
"Jorge Larralde","Auditor Contable",9,5
"Marta Fernández","Auxiliar contable",8,9
"Rita Jordán","Auxiliar contable",7,9
"Mario Loureiro","Facturista",6,5
"Federico Reitman","Gerente Administrativo",5,3
"Flavia González","Gerente Financiera",4,3
"Ramiro Lagrán","Control Financiero",6,4
"Rosario Montoya","Directora Administrativa",3,1
"Mauro Cardoso","Director de Operaciones",2,1
"Carlos Cruz","Gerente General",1,0
"Claudia Maqueda","Gerente de Logística",21,2
Esto no es más que un pequeño organigrama que usaremos de muestra. Contiene el nombre de cada persona en una empresa, su cargo, un id, y el id de la persona a quien reporta (su jefe).

Ahora crea un formulario con un grid al que pondremos 3 columnas:
Deja la primera bastante angosta pues sólo mostrará una letra (en reaildad, un signo más o un menos), las otras dos más o menos iguales, para el nombre y cargo.

No hay propiedades importantes, pero te conviene dejar la DataSession como privada porque es más sencillo trabajar así.

En el grid sólo indica el RecordSource = "Tabla", y a cada columna ponle Sparse en .F. (para que se vea mejor). La primera también conviene ponerla con Alignment = Centered.

Vamos al código (verás que es poco):

Métodos del form:
PROCEDURE Load
   USE arbol Order reporta
   
   * El cursor Tabla es una copia de la tabla, pero ordenada
   * jerárquicamente y con campos adicionales
   Create Cursor Tabla ( ;
    signo     C( 1), ;
    nombre    C(30), ;
    cargo     C(30), ;
    id        I, ;
    reporta   I, ;
    cadena    C(250), ;
    visible   L   )
ENDPROC


PROCEDURE Init
   Select Arbol

   Locate for Empty( reporta )    && Busca al nodo principal (no tiene jefe)

   thisform.CargaArbol( id, 0, ";" )  && Método recursivo que carga el árbol

   Select Tabla   && Se ubica en el primer registro
   locate
ENDPROC

PROCEDURE cargaarbol
   * ID del nodo, nivel de profundidad, cadena de jerarquía
   lParameters tnID, tnNivel, tcCadena

   Local lnRegistro

   Select Arbol
   Scatter memvar   && Copia los datos
   m.nombre = Replicate( "·", 3 * tnNivel ) + m.nombre   && indenta el nombre según el nivel
   m.cadena = tcCadena
   m.visible = .t.    && Inicia mostrando todo el árbol
   Insert into Tabla from memvar

   if Seek( tnID )    && Si tiene subordinados

      replace in Tabla signo with "-"   && Indica que lo tiene

      Scan while reporta = tnID   && Recorre los subordinados

         lnRegistro = Recno()     && Guarda el registro para poder continuar reocrriendo

         * Entra en el siguiente nivel de recursión para agregar al subordinado
         * El último parámetro es una cadena que contiene el "árbol genealógico" de cada nodo
         * ATENCION: Esto implica que hay un límite en el nivel de profundidad a manejar
         thisform.CargaArbol( Arbol.Id, tnNivel + 1, tcCadena + Transform(reporta) +";" )

         Go lnRegistro   && Como en la recursión puede haberse movido, vuelve a donde estaba
      EndScan
   endif
ENDPROC

PROCEDURE expande
   * Esto es llamado solamente al hacer doble click en un + ó un - en la grilla
   Lparameters tnID, tcSigno

   If !Empty( signo )   && Si no hay + ni - no hace nada

      Set filter to   && Quita todo el filtro
      * Marca como visible (si había un +) o invisible (si había un -)
      * a todos los subordinados (a todo nivel) del nodo indicado
      replace all visible with (tcSigno = "+") for ";"+ Transform( tnID ) +";" $ cadena
      Set Filter To visible   && Vuelve a filtrar los no visibles
      Locate for id = tnID    && Regresa al registro del click
      replace signo with Iif( tcSigno = "+", "-", "+" )  && Cambia el signo
   EndIf

   thisform.Refresh()  && Refresca el formulario, así vemos lo que pasó finalmente
ENDPROC
DoubleClick del textbox de la primer columna:
* Solamente llama al método del formulario
* No, poner todo es código aquí sería una salvajada. 
* En un evento no debe haber más de dos o tres líneas
thisform.expande( Tabla.id, Tabla.signo )
¿Se entiende lo que hago?

Básicamente todo se resume a cargar todo en un cursor que tiene más que nada un campo para el signo + ó - (como un treeview), y fundamentalmente, un campo que guarda toda la cadena de padres hacia arriba de cada registro. Esto me permite que yo pueda recorrer rápidamente toda su descendencia (con el operador $).

Hay formas más elegantes pero también más críticas de hacerlo. Si te gusta el resultado (que debes trabajar un poco visualmente), entonces es fácil mejorarlo.

Lo importante aquí es el criterio de mostra u ocultar los hijos de un nodo cualquiera. Verás que el resultado final es prácticamente el mismo que el de un treeview, pero con la ventaja de que al tratarse de una grilla tienes todo prolijamente encolumnado, menos el nombre (que personalmente me gusta indentar con esos puntitos), para mostrar claramente la jerarquía.

Bueno, Mauricio, espero que te sirva la idea y nuevamente disculpa haberte tenido en vilo estos días. Ojalá te guste la idea.

Saludos,
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform