Ver Mensaje Individual
  #4  
Antiguo 11-09-2008
Avatar de jcarteagaf
[jcarteagaf] jcarteagaf is offline
Miembro Premium
 
Registrado: abr 2006
Ubicación: La Paz, Bolivia
Posts: 651
Reputación: 19
jcarteagaf Va por buen camino
Tengo una tabla con la siguiente estructura:

Código SQL [-]
CREATE TABLE Arbol (
IDOPCION INT NOT NULL,
IDPADRE INT NOT NULL DEFAULT 0,
DESCRIPCION VARCHAR(50),
CONSTRAINT ArbolKey PRIMARY KEY (IDOPCION))

En esa tabla guardo la información de la estructura ciclica.

El siguiente procedimiento me devuelve la información de la tabla
Código SQL [-]
CREATE PROCEDURE Arbol_ABM_Opciones
-- =============================================
-- Author:        Juan Carlos Arteaga
-- Create date: 17/08/2008
-- Description:    Genera el Arbol de Opciones para el ABM
-- =============================================
AS
BEGIN
    SET NOCOUNT ON;

    CREATE TABLE #work (lvl int, IdOpcion int) 
    CREATE TABLE #Opciones (seq int identity, lvl int, IdOpcion int) 
 
    DECLARE @lvl int, @curr int 
    SET @lvl=1
    INSERT INTO #work (lvl, IdOpcion)
    SELECT 1,IDOPCION
    FROM Arbol
    WHERE IdPadre=0
    
    WHILE (@lvl > 0)
    BEGIN 
        IF EXISTS(SELECT * FROM #work WHERE lvl=@lvl)
        BEGIN 
            SELECT TOP 1 @curr=IdOpcion FROM #work 
            WHERE lvl=@lvl 
 
            INSERT #Opciones (lvl, IdOpcion) VALUES (@lvl, @curr) 
 
            DELETE #work 
            WHERE lvl=@lvl and IdOpcion=@curr 
 
            INSERT #work 
            SELECT @lvl+1, IdOpcion 
            FROM Arbol 
            WHERE IdPadre=@curr 
                AND IdPadre <> IdOpcion 
 
            IF (@@ROWCOUNT > 0)
                SET @lvl=@lvl+1 
        END
        ELSE 
            SET @lvl=@lvl-1 
    END 
 
    SELECT d.seq,d.IdOpcion,i.Descripcion,i.IdPadre
    FROM #Opciones d
    JOIN Arbol i ON (d.IdOpcion=i.IdOpcion) 
    ORDER BY seq 

    DROP TABLE #Work
    DROP Table #Opciones
END

Todos los nodos raiz (puedo tener mas de uno) tienen como padre el valor 0.

Ya en Delphi cargo esta estructura en un TTreeView (tvDatos) usando el siguiente procedimiento (spArbolABM es el TADOStoredProc que llama al anterior Procedimiento Almacenado):

Código Delphi [-]
Type
   // Para almacenar datos que quiero asociar a cada nodo
   PItem = ^TItem;
  TItem = record
    IdOpcion : integer;
  end;

...

var
  tnNodoActual : TTreeNode;  // Siempre apunta al nodo seleccionado

...

procedure TfrmABMMenu.Cargar_Arbol;
var
  TPrimerNodo: TTreeNode;
  i: integer;
  MyItem : PItem;

  procedure Rama(iCodigo: Integer; NodoPadre: TTreeNode);
  // Procedure recursivo que carga una rama
  var
    iCodPadre: integer;
    TNodoPadre: TTreeNode;
  begin
    if (spArbolABMIDPADRE.Value = iCodigo) then
      while (spArbolABMIDPADRE.Value = iCodigo) and (not spArbolABM.EOF) do
      begin
        inc(i);
        new(MyItem);
        MyItem.IdOpcion := spArbolABMIDOPCION.AsInteger;
        TNodoPadre := tvDatos.Items.AddChildObject(NodoPadre,
          spArbolABMDESCRIPCION.AsString,MyItem);
        iCodPadre := spArbolABMIDOPCION.Value;
        spArbolABM.Next;
        Application.ProcessMessages;
        Rama(iCodPadre, TNodoPadre);
      end;
  end;
begin
  i := 0;
  tvDatos.Items.Clear;
  spArbolABM.close;
  spArbolABM.Open;
  Screen.Cursor := crHourGlass;
  try
    if not spArbolABM.IsEmpty then
      Rama(0, nil);
  finally
    Screen.Cursor := crDefault;
    tvDatos.Selected := tvDatos.Items.GetFirstNode;
    tnNodoActual := tvDatos.Selected;
  end;
  spArbolABM.close;
end;

Espero que sea de utilidad.

Saludos
Responder Con Cita